如何在TypeScript条件类型中严格检查含可选字段的类型相等性
TypeScript 实现类型严格相等匹配(包含可选字段)
你遇到的问题是因为TypeScript采用结构类型系统,Fish的必填属性完全符合Elephant的必填结构,所以Fish extends Elephant会被判定为true,导致MyCondition<Fish>进入第一个分支返回"Elephant!"。要实现严格匹配(包括可选字段的差异),需要验证类型的双向兼容性,也就是两个类型必须完全一致。
解决方案:使用辅助类型做严格相等判断
先定义一个IsStrictEqual辅助类型,用来检测两个类型是否完全一致:
type IsStrictEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
这个类型的核心逻辑是:只有当A和B的类型完全相同时,两个泛型函数的类型才会被TypeScript判定为相等。如果A和B存在任何差异(比如可选属性不同、属性类型不同),函数类型就不匹配。
修改后的MyCondition类型
结合辅助类型,改写MyCondition来实现严格匹配:
interface Elephant { id: string; name: string; trunk?: number; } interface Fish { id: string; name: string; gills?: number; } type IsStrictEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false; type MyCondition<Animal> = IsStrictEqual<Animal, Elephant> extends true ? "Elephant!" : IsStrictEqual<Animal, Fish> extends true ? "Fish!" : "Not Fish or Elephant"; // 测试结果 type TestElephant = MyCondition<Elephant>; // 结果:"Elephant!" type TestFish = MyCondition<Fish>; // 结果:"Fish!" type TestPlain = MyCondition<{id: string; name: string}>; // 结果:"Not Fish or Elephant"
也可以直接整合逻辑(无需辅助类型)
如果不需要复用严格相等判断,也可以直接把逻辑写进MyCondition:
type MyCondition<Animal> = (<T>() => T extends Animal ? 1 : 2) extends (<T>() => T extends Elephant ? 1 : 2) ? "Elephant!" : (<T>() => T extends Animal ? 1 : 2) extends (<T>() => T extends Fish ? 1 : 2) ? "Fish!" : "Not Fish or Elephant";
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

