"请考虑使用映射对象类型." - 什么是映射对象类型,我如何在这里使用它?

Dan*_*ser 24 typescript

interface Foo { 
    [foo: "hello" | "world"]: string;
}
Run Code Online (Sandbox Code Playgroud)

我收到一条错误消息

An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
Run Code Online (Sandbox Code Playgroud)

什么是映射对象类型,以及如何使用它?

Dan*_*ser 24

映射对象类型对一组单例类型进行操作,并生成一个新的对象类型,其中每个单例都转换为属性名称.

例如,这个:

type Foo = {
    [K in "hello" | "world"]: string
};
Run Code Online (Sandbox Code Playgroud)

相当于

type Foo = {
    "hello": string;
    "world": string;
};
Run Code Online (Sandbox Code Playgroud)

请记住,映射的对象类型是一个不同的类型操作符 - 大括号中的语法不能用于接口,也不能用于与其他成员的对象类型.例如

interface Foo {
    [K in "hello" | "world"]: string
}
Run Code Online (Sandbox Code Playgroud)

产生以下错误:

A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
Run Code Online (Sandbox Code Playgroud)

映射的对象类型对许多不同的东西都很有用.在这里阅读更多内容:http://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types

  • @ironchicken,是的,您只需在关闭“]”后添加“?”,更多详细信息请参见:/sf/answers/3689058201/ (10认同)
  • 请注意,答案将“interface”更改为“type” - 这对我来说是解决方案。 (6认同)
  • 我想指出其中的区别。为了创建映射类型,我们将“**”中的 **":"** 替换为 **"。并在“hello”中变成 `[foo | “世界”]` (4认同)
  • @ironchicken你可以做`type Foo = { hello: string; 世界?:从来没有;} | { 世界:字符串;你好?:从不}`。您还可以扩展它以接受通用联合/值以使其可重用:`type Foo = OnlyOneProperty<"hello" | “世界”,字符串>`。有关示例用法,请参阅 [playground](https://codesandbox.io/s/typescript-onlyoneproperty-72xy5?file=/index.ts)。 (3认同)
  • 有没有这样的版本,该类型只能具有一个名称必须为“ hello”或“ world”的属性? (2认同)

Chr*_*der 17

这是无效的:

    type DirectiveType = 'package-as' | 'externals' | 'move-folders' | 'ignore';
    type Directives = { [key:DirectiveType]?: RootDirectives };
    
    export class PkgmetaFile {
        private _directives: Directives = {};
    }
Run Code Online (Sandbox Code Playgroud)

但这是有效的:

    type DirectiveType = 'package-as' | 'externals' | 'move-folders' | 'ignore';
    type Directives = { [Key in DirectiveType as string]?: RootDirectives };
    
    export class PkgmetaFile {
        private _directives: Directives = {};
    }
Run Code Online (Sandbox Code Playgroud)

  • 您能否对您的答案提供更多见解?试图在没有解释的情况下理解答案可能会导致误解。 (3认同)
  • 我可以通过简单地在“DirectiveType”末尾使用“as string”来从联合类型推断映射对象的键 (2认同)
  • 这似乎接受任何字符串作为键,而不仅仅是 DirectiveType (2认同)