您如何定义具有键字符串索引但具有特定类型的已知键的 TypeScript 接口?

Posted

技术标签:

【中文标题】您如何定义具有键字符串索引但具有特定类型的已知键的 TypeScript 接口?【英文标题】:How do you define a TypeScript interface with a Key String index but known keys with specific types? 【发布时间】:2020-10-20 21:08:38 【问题描述】:

如何定义带有 Key String 索引但具有特定类型的已知键的 TypeScript 接口,以便可以在映射中引用该键?

示例界面(这不起作用)

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;
  ;

这是这样使用的,

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%",
  ,
;

这是我映射转换后的对象以及引用键的位置。

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>

【问题讨论】:

你的意思是***.com/a/39281228/863110吗? 我看到在发布我的问题之前,它解决了具有已知键子属性的未知键,但我知道我需要使用字符串键引用的键和已知子属性。也许我的问题不在于类型的定义,而在于数组的映射。 我不确定我是否理解。你的代码有什么问题?错误的自动完成?转译错误? 如果我使用 [key: string]: column 或 Record,则不会自动完成。键是通用字符串,因此 .map 可以工作,但我没有自动完成该键,只有它的属性。如果我在没有指明键是字符串的情况下定义它,我会在 .map 上收到打字稿错误,因为我正在使用 columns[key] 创建列标题。 您可以执行类似this 的操作。或者您可以使用Object.entries 而不是Object.keys,这样您就不必转换该值。就像这样:Object.entries(COLUMNS).map(([key, value]) =&gt; ( &lt;span key=key style= width: value.width &gt; value.label &lt;/span&gt; )) 【参考方案1】:

您可以为可能的键声明一个类型

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

然后接口将使用该类型作为计算键使用 in 关键字

type IColumns = [key in Prop]: column

现在你可以使用那个界面了

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%",
  ,
;

关于地图,您有两种选择:

    使用Object.keys,但将密钥大小写为Prop
(Object.keys(COLUMNS) as Array<Prop>).forEach(key => ...)
    使用Object.entries 这样value 就已经是Prop
Object.entries(COLUMNS).map(([key, value /* :Prop */])

playground

【讨论】:

以上是关于您如何定义具有键字符串索引但具有特定类型的已知键的 TypeScript 接口?的主要内容,如果未能解决你的问题,请参考以下文章

打字稿中具有联合类型键的松散类型对象

具有未知键的对象的打字稿类型,但只有数值?

如何在 PHP 中将具有已知键的数组元素移动到数组的末尾?

如何解析具有相同键的不同数据类型的改造对象的json数组

使用 keyof 提取仅具有特定类型值的键的字符串文字联合

为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值