如何将泛型类类型创建为另一种类型的子集



我正在尝试创建一个泛型类型,该泛型类型被限制为另一个特定类型的子集。不应允许它添加新属性或重写现有属性的类型,但应允许它仅实现指定类型的子集。这是我所期望的:

type Foo = { a: string; b: number; }
// Case1: valid
new MyClass<{ a: string }>()
// Case2: invalid (does not exist in both types)
new MyClass<{ b: number }>()
// Case3: invalid (does not exist in both types)
new MyClass<{ c: string }>()
// Case4: invalid (does not exist in both types)
// invalid (wrong type of a)
new MyClass<{ a: number }>()
// Case5: invalid (wrong type of a)
new MyClass<{ a: undefined }>()
new MyClass<{ a: null }>()

我需要的是这样的东西:

// Pseudo code (subsets does not exist):
class MyClass<T subsets Foo> {}

extends Foo做的事情,我不想要:

  1. 允许声明其他属性(案例 3 有效(
  2. 强制执行Foo的所有属性(案例 1 无效(

extends Partial<Foo>做的事情,我不想要:

  1. 允许声明其他属性(案例 3 有效(
  2. 可以undefined所有属性的值

当前状态

我创建了一个类型,该类型创建了另一种类型的子集:

type Subset<T extends S, S> = Pick<T, keyof S>

但我无法让它作为类的约束......

我们可以创建一个不允许指定任何额外成员的限制,方法是强制要求如果存在任何额外的属性,则它们属于never类型。我们可以使用Exclude<keyof T, keyof S>来仅获取额外的密钥并Record

type Foo = { a: string; b: number; }
type Subset<T, S> = Pick<S, Extract<keyof T, keyof S>> & Partial<Record<Exclude<keyof T, keyof S>, never>>
class MyClass<T extends Subset<T, Foo>> {
constructor(public t?:T){
if(t == null) return;
// t has no accessible members as far as the compiler is concerned 
// but we can assign it to Partial<Foo> and access fields like this
let d: Partial<Foo> = t; 
d.a // works
}
}
// Case1: valid
new MyClass<{ a: string }>()
// Case2: invalid (does not exist in both types)
new MyClass<{ b: number }>()
// Case3: invalid (does not exist in both types) 
// This would be invalid under extends Partial<Foo> also
new MyClass<{ c: string }>()
// Case3b: invalid (has extra props)
// This would be valid under extends Partial<Foo> but is not under Partial<Foo> & Record<Exclude<keyof T, keyof Foo>, never>
new MyClass<{  a: string, c: string }>()
// Case4: invalid (does not exist in both types)
// invalid (wrong type of a)
new MyClass<{ a: number }>()
// Case5: invalid (wrong type of a) only with strict null checks !
new MyClass<{ a: undefined }>()
new MyClass<{ a: null }>()

游乐场链接

相关内容

最新更新