![](/img/trans.png)
[英]Typescript - how can a exclude a type from a generic type without using Exclude<>?
[英]Using typescript Exclude with generic type
我的基于 TypeScript 的 Nodejs 项目中依赖项的例行更新导致我在用于管理mongoose模型的通用类中收到 TypeScript 编译错误。 我已经将问题缩小到似乎是 TypeScript 处理泛型类型的问题。
我构建了以下最小示例:
interface I {
p: string;
}
class Foo<T extends I> {
exclude: Exclude<'p', 'q'> = 'p'; // OK
excludeI: Exclude<keyof I, 'q'> = 'p'; // OK
excludeT: Exclude<keyof T, 'q'> = 'p'; // TS2322: Type '"p"' is not assignable to type 'Exclude<keyof T, "q">'.
}
请注意, excludeI
(编译良好)和excludeT
(由于给定错误无法编译)的类型之间的唯一区别是后者使用泛型类型T
而不是接口类型I
。
由于T
被指定为扩展I
,我希望这两行得到相同的对待。 事实上,似乎keyof
运算符可以互换使用它们:
class Foo<T extends I> {
keyof: 'p' = 'p'; // OK
keyofI: keyof I = 'p'; // OK
keyofT: keyof T = 'p'; // OK
}
我在 TypeScript Playground 上使用了这个例子来试验不同的 TS 版本,它似乎不是依赖于版本的行为。
任何人都可以阐明Exclude<> 的情况吗?
这是 TypeScript 编译器的限制。 对于依赖于未指定泛型类型参数的条件类型,编译器通常无法验证值的可赋值性。 在这种情况下,条件类型的评估会推迟到指定类型参数之前,并且在此之前,类型对编译器或多或少是不透明的。
type Exclude<T, U> = T extends U ? never : T;
由于T
是泛型类型参数,因此Exclude<keyof T, 'p'>
是依赖于泛型类型参数的条件类型。 在Foo
类定义内部, T
是未指定的,因此您会在那里看到编译器的一些不智能的行为。
这是几个 GitHub 问题的主题,例如microsoft/TypeScript#33484关于Omit
无法识别这种可分配性( Omit
当前使用Exclude
实现),或microsoft/TypeScript#28884关于Pick<T, K> & Omit<T, K>
不被视为可分配给T
或microsoft/TypeScript#36737关于如何在返回通用条件类型的函数中无法轻松返回值。
那么,你怎么能继续呢? 这里的正确答案可能只是接受你比编译器更聪明,并使用类型断言告诉编译器你确定你正在做的事情是安全的,即使编译器不是:
excludeT = "p" as Exclude<keyof T, "p">; // okay
或者,如果您可以使用特定类型而不是泛型类型,那么编译器可以更轻松地进行推理,如您所见:
excludeI: Exclude<keyof I, 'q'> = 'p'; // OK
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.