如何从TypeScript字符串联合类型中移除string类型?
如何实现移除联合类型中的
string并保留字面量类型? 我从API生成的TypeScript类型里,遇到了这样的联合类型:
type Foo = 'foo' | 'bar' | string
我需要移除其中的宽泛string类型,只保留'foo' | 'bar'这类字符串字面量,也就是实现一个RemoveStringButKeepConstants类型,让:
type NarrowFoo = RemoveStringButKeepConstants<Foo> // ^? 'foo' | 'bar'
之前尝试的两种方案都没达到预期:
type Attempt1 = Exclude<Foo, string> // 结果是never,无法保留字面量 type Attempt2 = `${Foo}` // 结果还是string,没有收窄类型
也考虑过const类型参数,但不知道如何运用。
解决方案
可以利用TypeScript条件类型的特性,通过判断类型是否为宽泛的原始类型来过滤:
type RemoveStringButKeepConstants<T> = T extends string ? (string extends T ? never : T) : T; // 验证效果 type Foo = 'foo' | 'bar' | string; type NarrowFoo = RemoveStringButKeepConstants<Foo>; // NarrowFoo 最终类型为 'foo' | 'bar'
原理说明
- 当泛型
T匹配到宽泛的string时,string extends T条件成立,返回never,从而将其排除。 - 当
T匹配到字符串字面量(如'foo')时,string extends 'foo'不成立,直接返回T本身,保留字面量类型。
如果需要支持更多原始类型(比如排除宽泛number/boolean,保留对应字面量),可以扩展这个类型:
type RemovePrimitiveButKeepLiterals<T> = T extends string ? (string extends T ? never : T) : T extends number ? (number extends T ? never : T) : T extends boolean ? (boolean extends T ? never : T) : T; // 测试混合类型 type Mixed = 'a' | 123 | boolean | string | number; type Narrowed = RemovePrimitiveButKeepLiterals<Mixed>; // Narrowed 类型为 'a' | 123 | true | false
内容的提问来源于stack exchange,提问作者Vencovsky
相关产品推荐
相关产品推荐

