


























这是一个创建于 651 天前的主题,其中的信息可能已经有所发展或是发生改变。
服了 TypeScript 这货了,符合我对微软的刻板印象,最近几年似乎每次碰到看不明白的语法出错,都是在 TypeScript ,这货无数细节太微妙了。
interface Elements {
div: { id: number; name?: string; color: string; x: string }
a: { id: number; name?: string; href: string; x: string }
}
declare function getProps<T extends Record<any, any>>(obj: T, keys: (keyof T)[]): void
function Foo<T extends 'div' | 'a'>(tag: T, props: Omit<Elements[T], 'x'>) {
// 这行报错 Type 'string' is not assignable to type 'Exclude<keyof Elements[T], "x">'
getProps(props, ['id'])
}
Foo('a', { id: 1, href: '#' })
// 我以为是因为 Omit 只能放单个对象,试了下多个也行啊。
type kkk = Omit<Elements['div' | 'a'], 'x'>
把 `function Foo<T extends 'div' | 'a'>(tag: T, props: Omit<Elements[T], 'x'>)`
改成 `function Foo<T extends 'div' | 'a'>(tag: T, props: Omit<Elements['div' | 'a'], 'x'>)` 就不会报错。
那这个 `T` 不就是 `'div' | 'a'` 吗?这 tm 二者到底有什么微妙区别导致代码一个报错一个没错?
1 ZZITE 2024 年 9 月 2 日我觉得应该在保持第一种写法的情况下,在 getProps 传参这里使用断言处理,即 getProps(props, ["id"] as (keyof Omit<Elements[T], 'x'>)[]); 和 Omit 无关,两种情况的区别在于第一种 Omit<Elements[T], 'x'>的结果是泛型参数,这里 TS 是不会做出“ ‘id’一定存在于这个泛型中”的这种推断的,它无法确定具体的类型结构。这里的报错具体来说其实是“ “id' is not assignable to type 'Exclude<keyof Elements[T], "x">'”。但我们知道"id"是有效的 key😂,所以在传入“id”的时候对它做个类型断言。 至于第二种写法,Omit<Elements['div' | 'a']是一个具体的联合类型,ts 是可以确定整个类型结构的,也可以推断出"id"是一个符合联合类型结果的有效 key |
3 june4 2024 年 9 月 2 日@june4 这里的问题是 Omit<Elements[T], 'x'> 这里的 Omit 操作结果出问题了。如果去掉 Omit ,直接用 Elements[T],那一点问题都没有。 但这个 Omit 我似乎也看不出为什么会出问题? |
4 rm2788 2024 年 9 月 2 日@june4 #2 ts 能力是由限的,你觉得是,但是它处理起来就比较麻烦,这也是 as 的作用之一,用在你比编译器知道更多的信息,一般给泛型套上另一个 Conditional Type 大部分就不会继续计算了,所以没必要纠结这些 |
5 csl123 2024 年 9 月 2 日Omit 改成 Exclude 好像就可以了,原因没细看。 ``` typescript interface Elements { type E<T extends 'div' | 'a'> = Exclude<keyof Elements[T], 'x'> // type EDiv = "id" | "name" | "color" type O<T extends 'div' | 'a'> = Omit<keyof Elements[T], 'x'> /** |
6 ZZITE 2024 年 9 月 2 日@june4 #3 嗯嗯,这里 Elements[T]如你所说,通过 T extends 'div' | 'a' 是可以推断出具体类型结构的,但在 Omit 后返回了一个新类型,这个新类型是抽象的,就是我说的泛型参数,这里是无法推断出 id 一定存在于新类型的类型结构里的。 |
7 june4 2024 年 9 月 2 日@ZZITE 也许是这样。 |
8 zhangdroid 2024 年 9 月 2 日可以看看这个 issue: https://github.com/microsoft/TypeScript/issues/39556 这样就可以 work 了: ```ts declare function getProps<T extends Record<any, any>>(obj: T, keys: (keyof T)[]): void type SimpleUnionOmit<T, K extends string | number | symbol> = T extends unknown ? Omit<T, K> : never function Foo<T extends 'div' | 'a'>(tag: T, props: SimpleUnionOmit<Elements[T], 'x'>) { |
10 cosmos601 2024 年 9 月 2 日写这种复杂函数的 ts 类型是真的想死,半小时写完的业务代码,搞类型半小时 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。