Typescript 扩展了狭窄的通用类型
Typescript Expands Narrowed Generic Type
我有这个代码:
type Constructable = {new(...args: any[]): any, prototype: any}; // Represents a class (that can be called with new)
type WithOnlyType<O, T> = {[P in keyof O as O[P] extends T? P: never]: O[P]}; //
// Override a constructor with name C in a scope S
function extendConstructor<
S,
T extends WithOnlyType<S, Constructable>,
C extends keyof T>
(
className: C, constructor: (...args: ConstructorParameters<T[C]>) => any, scope: S) {
...}
但是,ConstructorParameters<T[C]>
是错误的,因为 Type 'T[C]' does not satisfy the constraint 'abstract new (...args: any) => any'.
这很奇怪,因为 T 只包含满足该要求的值(Constructable
),而 C 是 keyof T
。但是,在错误的更下方(底部),我发现:
Type 'S[string]' is not assignable to type 'abstract new (...args: any) => any'
这是真的,S 可以有比 类 更多的值,但是,T 比 S 窄得多,C 比字符串窄得多。如何阻止 tsc 扩展这些类型?
Typescript 不会遵循映射的条件类型将导致 T[C]
是可构造的。
您可以重新构造您的类型参数并使其工作:
function extendConstructor<
S extends Record<C, Constructable>,
C extends keyof WithOnlyType<S, Constructable>>
(className: C, constructor: (...args: ConstructorParameters<S[C]>) => any, scope: S) {
}
注意:我建议将 scope
放在第一位,以便更好地完成密钥上的代码。
这是 TypeScript 的设计限制。有关类似问题的描述,请参阅 microsoft/TypeScript#30728。当 T
和 C
是都是未指定的泛型类型参数。您专门编写了 WithOnlyType
来保证这种约束,但是 WithOnlyType<S, Constructable>[keyof WithOnlyType<S, Constructable>]
或多或少对编译器来说是不透明的。
如果您想解决这个问题,可以使用 the Extract<T, U>
utility type。当你有一个 你 知道的类型 T
可以分配给类型 U
但编译器不知道这一点时,你可以写成 Extract<T, U>
T
个。编译器看到 Extract<T, U>
可分配给 U
,并且您知道 Extract<T, U>
最终将解析为任何 T
是什么(因为 Extract<T, U>
计算为任何联合T
的成员可分配给 U
).
所以如果你改变
ConstructorParameters<T[C]>
到
ConstructorParameters<Extract<T[C], Constructable>>
错误将消失。
我有这个代码:
type Constructable = {new(...args: any[]): any, prototype: any}; // Represents a class (that can be called with new)
type WithOnlyType<O, T> = {[P in keyof O as O[P] extends T? P: never]: O[P]}; //
// Override a constructor with name C in a scope S
function extendConstructor<
S,
T extends WithOnlyType<S, Constructable>,
C extends keyof T>
(
className: C, constructor: (...args: ConstructorParameters<T[C]>) => any, scope: S) {
...}
但是,ConstructorParameters<T[C]>
是错误的,因为 Type 'T[C]' does not satisfy the constraint 'abstract new (...args: any) => any'.
这很奇怪,因为 T 只包含满足该要求的值(Constructable
),而 C 是 keyof T
。但是,在错误的更下方(底部),我发现:
Type 'S[string]' is not assignable to type 'abstract new (...args: any) => any'
这是真的,S 可以有比 类 更多的值,但是,T 比 S 窄得多,C 比字符串窄得多。如何阻止 tsc 扩展这些类型?
Typescript 不会遵循映射的条件类型将导致 T[C]
是可构造的。
您可以重新构造您的类型参数并使其工作:
function extendConstructor<
S extends Record<C, Constructable>,
C extends keyof WithOnlyType<S, Constructable>>
(className: C, constructor: (...args: ConstructorParameters<S[C]>) => any, scope: S) {
}
注意:我建议将 scope
放在第一位,以便更好地完成密钥上的代码。
这是 TypeScript 的设计限制。有关类似问题的描述,请参阅 microsoft/TypeScript#30728。当 T
和 C
是都是未指定的泛型类型参数。您专门编写了 WithOnlyType
来保证这种约束,但是 WithOnlyType<S, Constructable>[keyof WithOnlyType<S, Constructable>]
或多或少对编译器来说是不透明的。
如果您想解决这个问题,可以使用 the Extract<T, U>
utility type。当你有一个 你 知道的类型 T
可以分配给类型 U
但编译器不知道这一点时,你可以写成 Extract<T, U>
T
个。编译器看到 Extract<T, U>
可分配给 U
,并且您知道 Extract<T, U>
最终将解析为任何 T
是什么(因为 Extract<T, U>
计算为任何联合T
的成员可分配给 U
).
所以如果你改变
ConstructorParameters<T[C]>
到
ConstructorParameters<Extract<T[C], Constructable>>
错误将消失。