首页 > 解决方案 > 检查一个类型是否作为另一种类型的属性存在

问题描述

我有一些类型:

interface IMyParentInterface {
    foo: string,
    items: IMyChildinterface[]
}

interface IMyChildinterface {
   id: number,
   bar: string,
}

我有一个使用接口的类:

class MyClass<T, D = keyof T> {...}

所以,我正在创建实例:

const class = new MyClass<IMyParentInterface, IMyChildinterface>(...)

因此,我想严格检查是否IMyChildinterface是用作IMyParentInterface属性的确切类型。

换句话说,我不应该做这样的事情:

const class = new MyClass<IMyParentInterface, TJustRandomType>(...)

不幸的是,typeof什么也没做

标签: javascripttypescript

解决方案


我们需要通过extends关键字将类型限制为特定的子集。考虑:

class MyClass<
T extends { items: any }, 
D extends T['items'][number] = T['items'][number]> { };

const a = new MyClass<IMyParentInterface, IMyChildinterface>(); //ok

interface Other {
    a: string
}
const b = new MyClass<IMyParentInterface, Other>(); //error

解释:

  • T extends { items: any }正如您所说的那样,我认为IMyParentInterface这不是您要使用的一种类型。然后我限制我们的第一个类型具有items属性
  • D extends T['items'][number] = T['items'][number]- 限制第二种类型将是第一种items属性项类型的类型。
  • 看看现在放置第二种类型不是nesesery,因为默认情况下它会是你想要的

选择所需密钥的更通用解决方案:

// proposition with picking the property
class MyClass<
Prop extends PropertyKey, 
T extends Record<Prop, any>, 
D extends T[Prop][number] = T[Prop][number]> { }
const a = new MyClass<'items', IMyParentInterface, IMyChildinterface>(); //ok

interface Other {
    a: string
}
const b = new MyClass<'items', IMyParentInterface, Other>(); //error

通过推断数组类型属性的类型更加通用

// proposition with every array type property
type PickByValue<T, V, _Keys extends keyof T = {
    [K in keyof T]: T[K] extends V ? K : never
}[keyof T]> = Pick<T, _Keys>

class MyClass<
    T extends (Array<any> extends T[keyof T] ? object : never),
    D extends _E[keyof _E][number],
    _E extends Record<any, Array<any>> = PickByValue<T, Array<any>>
    > { }
const a = new MyClass<IMyParentInterface, IMyChildinterface>(); //ok

interface Other {
    a: string
}
const b = new MyClass<IMyParentInterface, Other>(); //error

推荐阅读