当父键是通用键时,限制子接口的有效键

时间:2019-04-12 20:33:46

标签: typescript

当通过通用键扩展父级时,是否有一种方法可以使子类型具有一组有限的有效键?例如:

class SomeClass {
  constructor(public value: number) {}
}

interface IParent {
  [key: string]: SomeClass;
}

interface IChild extends IParent {
  a: SomeClass;
  b: SomeClass;
}

const o: IChild = {
  a: new SomeClass(1),
  b: new SomeClass(2),
  c: new SomeClass(3) // I'd like this to be an error
};

我希望将扩展IParent的所有内容强制为所有键具有SomeClass的值,但是理想情况下,分配不是IChild界面中明确列出的任何键的任何内容,导致错误。

这可能吗?

1 个答案:

答案 0 :(得分:2)

您可以只使用映射类型:

type ValidKeys = 'a' | 'b';
type IParent = { [key in ValidKeys]: SomeClass };

interface IChild extends IParent { } // You don't really need this interface.

const o: IChild = {
  a: new SomeClass(1),
  b: new SomeClass(2),
  c: new SomeClass(3),
  // Object literal may only specify known properties, and 'c' does not exist in type 'IChild'.
};

但是请注意,这只会保护您免于声明具有无效属性的文字IChild。这仍然是完全有效的:

const m = {
  a: new SomeClass(1),
  b: new SomeClass(2),
  c: new SomeClass(3),
};

const o: IChild = m;

您也可以将IParent设为通用,以便能够有多个孩子,

type IParent<T extends string> = { [key in T]: SomeClass };

type IHasAB = IParent<'a' | 'b'>;
type IHasXY = IParent<'x' | 'y'>;

const ab: IHasAB = {
    a: new SomeClass(1),
    b: new SomeClass(2),
};
const xy: IHasXY = {
    x: new SomeClass(3),
    y: new SomeClass(4),
};