我用两种不同的方式编写了一个嵌套的Omit
类型,但是对我来说更有意义的一种类型给出了复杂的类型提示,而一种较不直观的类型提示实际上看起来最好。去吧:
type HasSameNested = {
a: {
c: number; d: string
},
b: {
c: string; d: number
}
}; // flipped C and D types
type Omit2<T, K1 extends keyof T, K2 extends keyof T[K1]> = {
[P1 in keyof T]: P1 extends K1 ? {
[P2 in Exclude<keyof T[K1], K2>]: T[P1][P2]
} : T[P1]
}
type Omit2_2<T, K1 extends keyof T, K2 extends keyof T[K1]> = {
[P1 in keyof T]: P1 extends K1 ? {
[P2 in Exclude<keyof T[P1], K2>]: T[P1][P2]
} : T[P1]
}
type omit_union = Omit2<HasSameNested, 'a' | 'b', 'c'>;
let T6: omit_union;
T6.a; // works, type is { d: string }
T6.b; // works, type is { d: number }
type omit_union_2 = Omit2_2<HasSameNested, 'a' | 'b', 'c'>;
let T7: omit_union_2;
T7.a.d = 'a'; // works but types are ugly:
// a: { [P2 in Exclude<keyof HasSameNested[K1 & "a"], "c">]: HasSameNested[K1 & "a"][P2]; }
// d: d: HasSameNested[K1 & "a"]["d"]
T7.b.d = 4; // works but types are ugly, as above
将错误的类型分配给T7.b.d
或T7.a.d
确实会告诉我string is not assignable to number
,但我不明白,即使Exclude<keyof T[P1], K2>
,P1 in keyof T
和P1 extends K1
,为什么使用Exclude<keyof T[K1], K2>
仍会产生这种复杂的输入给出正确的类型。
答案 0 :(得分:2)
在我看来,这似乎是编译器中的错误。我刚刚提交了Microsoft/TypeScript#31326,并将从那里报告最新信息。祝你好运!
更新,2019年5月10日:一位语言设计师将其标记为bug。不知道何时将其修复,但至少我们知道您对该类型信息感到困惑是正确的。
更新,2019年5月11日:正如您所注意到的那样,此错误现在为fixed,并已合并到master
中。这意味着,如果您现在使用typescript@next
尝试代码,则应该看到新的行为:
type omit_union_2 = Omit2_2<HasSameNested, 'a' | 'b', 'c'>;
declare let T7: omit_union_2;
T7.a; // works, type is { d: string }
T7.b; // works, type is { d: number }
我看不到您的T6
和T7
类型之间的区别。因此,看起来这完全是由该编译器错误引起的,并且应该在2019年5月30日左右发布TypeScript 3.5时消失。
好的,祝你好运!