将对象属性限制为keyof接口

时间:2017-11-08 14:06:26

标签: typescript

此代码无法编译:

interface IFoo {
   a: number;
}

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

let obj: OFoo = { a: 1 };

我想要实现的目标是obj只能用具有有效属性的对象赋值,就像我写的那样:

let obj: IFoo = { a: 1};

但我需要通过keyof来实现。

感谢任何想法。

1 个答案:

答案 0 :(得分:4)

虽然您无法直接使用stringnumber之外的任何内容作为索引签名中的键类型(并且您对OFoo的定义会给您一个错误) ,可以使用mapped types将密钥限制为string的子类型。由于TFoo,a.k.a。keyof Foostring的子类型,因此您可以使用这样的映射类型:

type OFoo = { [K in TFoo]: any }; 

请注意,映射类型的语法与常规索引签名的语法不同。上面的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'

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

type Record<K extends string, T> = {
  [P in K]: T
}

或者,您可以认为:“Record<K, T>是一个对象,其中每个键都在K中,每个值都是T”。对您而言,KTFooTany

type OFoo = Record<TFoo, any>;  // same thing 

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