将对象属性限制为keyof接口

use*_*334 4 typescript

该代码将无法编译:

interface IFoo {
   a: number;
}

type TFoo = keyof IFoo;
type OFoo = { [key: TFoo]: any };

let obj: OFoo = { a: 1 };
Run Code Online (Sandbox Code Playgroud)

我要实现的目标是使obj仅可分配具有有效属性的对象,就像我写道:

let obj: IFoo = { a: 1};
Run Code Online (Sandbox Code Playgroud)

但是我需要通过keyof来完成。

感谢您的任何想法。

jca*_*alz 6

尽管您不能直接使用任何东西,string或者只能将其number用作索引签名中的键类型(并且您的定义OFoo会给您带来这种效果的错误),但是您可以将键限制为string使用映射类型的子类型。由于TFooaka keyof Foo是的子类型string,因此可以使用如下映射类型:

type OFoo = { [K in TFoo]: any }; 
Run Code Online (Sandbox Code Playgroud)

请注意,映射类型的语法与常规索引签名的语法不同。在TFoo以上,相当于允许键的类型,它只是"a"在你的情况,但也可能是字符串文字像工会"a"|"b"|"c",甚至string。与K上述是对应于一个参数类型为每个属性的密钥。(您实际上并不在乎,K因为每个属性的类型都是,any并且与无关K,但是K如果您愿意的话,您可能会习惯于选择特定的属性。)无论如何,让我们使用它:

let obj: OFoo = { a: 1 }; // okay
let obj = { }; // error, property 'a' is missing
let obj = { c: 1 }; // error, excess property 'c'
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我可能会使用如下Record<K,T>定义的内置标准库类型:

type Record<K extends string, T> = {
  [P in K]: T
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以考虑:“ a Record<K, T>是一个对象,每个键都在其中K,每个值都是一个T”。对于您来说,KTFooTany

type OFoo = Record<TFoo, any>;  // same thing 
Run Code Online (Sandbox Code Playgroud)

希望能有所帮助;祝好运!