为Typescript Record定义可选键列表

Jea*_*eri 7 typescript typescript-typings

我想输入一个只能有'a','b'或'c'键的对象.

所以我可以这样做:

Interface IList {
    a?: string;
    b?: string;
    c?: string;
}
Run Code Online (Sandbox Code Playgroud)

它们都是可选的!现在我想知道这是否只能用Record一行编写

type List = Record<'a' | 'b' | 'c', string>;
Run Code Online (Sandbox Code Playgroud)

唯一的问题是需要定义所有密钥.所以我结束了

type List = Partial<Record<'a' | 'b' | 'c', string>>;
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我可以想象有一个更好的方法来做到这一点没有偏见.还有另一种方法可以在Record中使键可选吗?

Fen*_*ton 29

您可以创建您的List类型的部分版本:

type PartialList = Partial<List>;
Run Code Online (Sandbox Code Playgroud)

如果您不想要中间类型,则可以在一行中完成所有操作:

type PartialList = Partial<Record<'a' | 'b' | 'c', string>>;
Run Code Online (Sandbox Code Playgroud)

最后,您可能会决定,对未来的自己最具表现力的是:

type List = {
    a?: string;
    b?: string;
    c?: string;
}
Run Code Online (Sandbox Code Playgroud)


Tit*_*mir 14

没有办法指定成员的可选性Record.根据定义,它们是必需的

type Record<K extends keyof any, T> = {
    [P in K]: T; // Mapped properties are not optional, and it's not a homomorphic mapped type so it can't come from anywhere else.
};
Run Code Online (Sandbox Code Playgroud)

如果这是您的常见方案,您可以定义自己的类型:

type PartialRecord<K extends keyof any, T> = {
  [P in K]?: T;
};
type List =  PartialRecord<'a' | 'b' | 'c', string>
Run Code Online (Sandbox Code Playgroud)

或者您也可以PartialRecord使用预定义的映射类型进行定义:

type PartialRecord<K extends keyof any, T> =  Partial<Record<K, T>>
Run Code Online (Sandbox Code Playgroud)

  • “没有办法指定`Record`成员的可选性”......你确定吗?据我所知,`Partial&lt;Record&lt;keyof T, any&gt;&gt;` 似乎就是这样操作的。自从做出这个答案以来,这是否有所改变? (4认同)
  • 啊,我现在看到他们专门询问如何在没有 Partial 的情况下做到这一点,我在第一句话中读了太多。mb (3认同)
  • @KOVIKO `Partial` 是一种不同的类型,问题是你是否可以为 `Record` 本身指定它。最后一个代码片段准确地展示了将 `Partial` 与 `Record` 组合以获得 `PartialRecord` 效果的能力 (2认同)

小智 14

也可以这样做:

type List = { [P in 'a' | 'b' | 'c']?: string }; // The `?` makes the keys optional
Run Code Online (Sandbox Code Playgroud)

例子:

const validList1: List = {
  a: 'hi'
}

const validList2: List = {
  b: 'hi',
  c: 'there'
}

const validList3: List = {
  a: 'oh',
  b: 'hi',
  c: 'there'
}
Run Code Online (Sandbox Code Playgroud)


bvd*_*vdb 6

除了解决方案之外Partial<Record<List, string>>,也许还有一个更明显的选择需要考虑。

相反,您可以将数据存储在地图中。

const map: Map<KeyType, ValueType> = new Map();
Run Code Online (Sandbox Code Playgroud)

从功能角度来看,没有太大区别。这实际上取决于具体情况,这是否是一个可行的替代方案。


Ale*_*nko 5

看起来在新版本的打字稿中,您可以执行以下操作

type YourUnion = 'a' | 'b' | 'c';   
type ObjectWithOptionalKeys = Partial<Record<YourUnion, string>>
const someObject: ObjectWithOptionalKeys {
  a: 'str', // works
  b: 1 // throws
}
// c may not be specified at all
Run Code Online (Sandbox Code Playgroud)