将类型缩小为其索引签名的属性

时间:2019-06-03 07:24:57

标签: typescript typescript-typings

我正在构建一个类型定义集,该类型定义集将根据用户提供的代表其“状态”模型的类型进行操作。

我需要做的一件事情就是缩小模型的类型,因为我产生了使用并暴露给它们的新类型。

我在缩小作为索引签名的对象的属性时遇到问题。

例如:

/**
 * Picks only the keys of a certain type
 * Taken from typelevel-ts
 */
type KeysOfType<A extends object, B> = {
  [K in keyof A]-?: A[K] extends B ? K : never;
}[keyof A];

interface Address {
  street: string;
  postCode: string;
}

interface Person {
  // I'd like to narrow to this property
  favouriteNumbers: {
    [id: string]: number;
  };
  name: string;
  address: Address;
}

type PersonIndexSignatures = Pick<
  Person, 
  KeysOfType<Person, { [key: string]:  any; }>
>;

type PersonIndexSignaturesKeys = keyof PersonIndexSignatures;
// "favouriteNumbers" | "address"

正如您在上面看到的,我尝试根据Person缩小{ [key: string]: any; }的同时产生了favouriteNumbersaddress键。

我有什么技巧可以将类型缩小为favouriteNumbers吗?

1 个答案:

答案 0 :(得分:1)

这里是一种方法:

首先,我们如何分辨Person["favouriteNumbers"]Person["address"]之间的区别?

这看起来很有希望:

type A = keyof Person["favouriteNumbers"];
// string | number

type B = keyof Person["address"];
// "street" | "postcode"

string扩展了A,但没有扩展B

type A = string extends keyof Person["favouriteNumbers"] ? true : false;
// true

type B = string extends keyof Person["address"] ? true : false;
// false

我们可以将其签入您的KeysOfType(您可能可以清理):

type KeysOfType<A extends object, B extends { [key: string]: any }> = {
  [K in keyof A]: A[K] extends B ? string extends keyof A[K] ? K : never : never;
}[keyof A];

然后:

type PersonIndexSignaturesKeys = keyof PersonIndexSignatures;
// "favouriteNumbers"