如何构造可赋值给泛型T但排除泛型U的TypeScript类型?
如何构造可赋值给但不可赋值给的类型
你需要的是一个属于T的子类型,但排除所有能赋值给U的实例。Exclude<T, U>在这里无效的原因是,Exclude仅适用于联合类型,它的作用是从联合类型中移除可赋值给目标类型的成员。而T是单个接口类型,并非联合,因此Exclude<T, U>直接返回T,无法过滤掉符合U的实例。
解决方案
要实现需求,我们需要约束X的foo属性不能是"baz",同时保留T的其他属性。可以通过交叉类型结合Exclude来定义:
interface T { foo: string; bar: number; } interface U { foo: "baz"; } // 定义X:继承T的所有属性,同时将foo约束为排除"baz"的string类型 type X = T & { foo: Exclude<string, "baz"> }; const xObj1: X = { foo: "test", // ✅ 合法,符合约束 bar: 4 }; const xObj2: X = { foo: "baz", // ❌ 报错:类型'"baz"'不能赋值给类型'Exclude<string, "baz">' bar: 2 };
如果想要更通用的写法(后续T或U的foo类型变化时无需修改X),可以这样写:
type X = Omit<T, "foo"> & { foo: Exclude<T["foo"], U["foo"]> };
原理说明
这种方式通过Omit<T, "foo">保留T中除foo外的所有属性,再通过Exclude<T["foo"], U["foo"]>将foo的类型限定为T["foo"]中排除U["foo"]的部分,从而确保X的实例既符合T的结构要求,又无法满足U对foo的字面量约束。
内容的提问来源于stack exchange,提问作者Chlod Alejandro
相关产品推荐
相关产品推荐

