TypeScript 提取作为泛型传递的Map类型中的非缩小类型联合

k10s72fa  于 5个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(53)

🔎 搜索词

提取,类型联合

🕗 版本与回归信息

  • 在版本5.33和5.4之间发生了变化

⏯ Playground链接

https://www.typescriptlang.org/play?ts=5.4.2#code/C4TwDgpgBAysBOBLAdgcwNIRAZwDwBUA+KAXigFEAPBAQwGNhcBrLAewDMoBvAWACgogqAG0AClBRQWIDlHxQa2OWIC6UCNQjIAJkuwIUqKAH4oogFxRkEAG4R4KyzWQh+AXwA0UfUjSF+-HSsyPpQAEYANqysYKRQBB6EABQAXpZwvhhYeEQAlKTEvAJQQSHAUOyWPoZxKe4BfCjA9uz00Ira3PyCAI4A7hBVBmj1fPwREOU06cNZOLgd-nxAA

💻 代码

type StringKeys<T> = Extract<keyof {
    [P in keyof T as T[P] extends string ? P: never]: any
}, string>

const bloop = <T,>(z: StringKeys<T>) => {
  const f: string = z
}

interface asd {
  qwe: string
}

let a: StringKeys<asd>

🙁 实际行为

z 不能分配给 stringbloop 函数中

🙂 预期行为

z 应该可以分配给 string ,因为我们提取了扩展字符串的键

关于问题的附加信息

在5.3.3上这工作得很好,并且在泛型具体化时(因此示例底部有 let)继续工作

wn9m85ua

wn9m85ua1#

条件类型很棘手,因为它们经常在泛型上下文中被推迟。这个版本可能相对容易工作(但实际上不是这样):

type StringKeys<T> = keyof {
  [P in keyof T as T[P] extends string ? P & string : never]: any;
};

const bloop = <T,>(z: StringKeys<T>) => {
  const f: string = z; // errors but shouldnt
};

作为解决方法,你可以使用这个版本:

type StringKeys<T> = keyof {
  [P in keyof T as T[P] extends string ? P : never]: any;
} &
  string;

const bloop = <T,>(z: StringKeys<T>) => {
  const f: string = z;
};
3duebb1j

3duebb1j2#

这个解决方法在我的实际代码库中有效,所以我暂时切换到这种方法 - 这是交集(而不是 Extract )导致非延迟评估的问题吗?

ut6juiuv

ut6juiuv3#

我猜这只是编译器知道 T & string 总是可以分配给 string,而不管 T 是什么(根据定义,因为 A & B 是分配给两者的值集合)

相关问题