简体   繁体   中英

How do you define a TypeScript interface with a Key String index but known keys with specific types?

How do you define a TypeScript interface with a Key String index but known keys with specific types, so that you can reference the key in a map?

Example Interface (This doesn't work)

interface column {
  label?: string;
  width: string;
}

export interface IColumns {
  [key: string]: {
    title: column;
    objectID?: number;
    url?: column;
    author: column;
    comments: column;
    points: column;
    archive: column;
  };
}

This is being used like so,

const COLUMNS : IColumns = {
  title: {
    label: "Title",
    width: "40%",
  },
  author: {
    label: "Author",
    width: "30%",
  },
  comments: {
    label: "Comments",
    width: "10%",
  },
  points: {
    label: "Points",
    width: "10%",
  },
  archive: {
    width: "10%",
  },
};

This is where I map over the converted object and what to reference the key.

const Stories: React.FC<{ stories: IStory[] }> = ({ stories }) => (
  <div className="stories">
    <div className="stories-header">
      {Object.keys(COLUMNS).map((key) => (
        <span key={key} style={{ width: COLUMNS[key].width }}>
          {COLUMNS[key].label}
        </span>
      ))}
    </div>

You can declare a type for the possible keys

type Prop = 'title' | 'author' | 'comments' | 'points' | 'archive';

Then the interface will use that type as computed key using the in keyword

type IColumns = {[key in Prop]: column}

Now you can use that interface

const COLUMNS : IColumns = {
  title: {
    label: "Title",
    width: "40%",
  },
  author: {
    label: "Author",
    width: "30%",
  },
  comments: {
    label: "Comments",
    width: "10%",
  },
  points: {
    label: "Points",
    width: "10%",
  },
  archive: {
    width: "10%",
  },
};

About the map, you have 2 options:

  1. Use Object.keys but case the key into Prop
(Object.keys(COLUMNS) as Array<Prop>).forEach(key => ...)
  1. Use Object.entries so the value will be already Prop
Object.entries(COLUMNS).map(([key, value /* :Prop */])

playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM