TypeScript 让(值空间)typeof给一个比所有typeof类型的联合更具体的类型,

h6my8fg2  于 4个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(71)

建议

🔍 搜索词

typeof typeof string literal value redeclare
在创建此问题之前,您搜索的关键词列表。请在这里写下它们,以便其他人更容易找到此建议并提供反馈。

✅ 可实现性检查清单

我的建议符合以下准则:

  • 这不会对现有的TypeScript/JavaScript代码造成破坏性的更改
  • 这不会改变现有JavaScript代码的运行时行为
  • 这可以在不根据表达式的类型发出不同的JS的情况下实现
  • 这不是一个运行时特性(例如库功能、具有JavaScript输出的非ECMAScript语法、JS的新语法糖等)
  • 此功能将与 TypeScript's Design Goals 一致。

⭐ 建议

如果一个值已知为特定的原始类型或类型的联合,例如 stringnumber | string ,那么 typeof typeof 应该返回确切的字符串字面量类型,例如 "string""number" | "string" ,分别对应。
换句话说:如果 typeof <value> 将知道返回其中一个或多个字符串字面量,那么 TypeScript 应该给出比仅 string 更具体的类型。

📃 动机示例

当变量旨在存储 typeof 表达式的结果时,TypeScript应该能够推断出其字符串字面量类型,而不仅仅是它是一个 string 原始类型。
这段代码中不应有错误:

let myTypeOf: 'number' | 'string';
myTypeOf = typeof 'abc';
myTypeOf = typeof 123;

今天:

Type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' is not assignable to type '"string" | "number"'.
  Type '"bigint"' is not assignable to type '"string" | "number"'.

💻 用例

请参阅此变量声明:https://github.com/typescript-eslint/typescript-eslint/pull/3891/files#diff-8a7d4566dbe9356145e8b86ccefa6d7a164c0b77818beb78d789e1089e9c4bc4R39
理想情况下,我们希望将其称为 let memberType: 'noInitializer' | 'number' | 'string' | undefined ,但稍后 typeof member.initializer.value 返回的是 string 而不是 'number' | 'string'
编辑:这也导致了 typescript-eslint/typescript-eslint#3453 ,所以这可能是一个bug?

ldioqlga

ldioqlga1#

在之前的讨论中提到了 #16314

u2nhd7ah

u2nhd7ah2#

解:

  1. 列出所有可能的情况。

  2. 计算每种情况下的概率,并将结果相加。

  3. 得到最终答案。

svmlkihl

svmlkihl3#

我理解原始类型 - boolean , number , string 很容易缩小,但仍然存在防御性编程的问题 - 例如,如果 x 缩小为 'number' ,如何允许 typeof x === 'undefined' ?
从类型系统的Angular 来看,这并不是那么明确。在这种情况下,当然TS可以“允许”这种“不必要的”检查,因为 undefined 是一个唯一的类型,但 'undefined' 根本不是。
我认为不幸的是,由于遗留标准,仍有大量的代码库使用 typeof x === 'undefined' 检查而不是 x === undefined ,所以这可能不是一件你可以“忽略”的事情。
也许可以将 'undefined' 合并到 typeof 中?但从API设计的Angular 来看,这确实有异味。
我个人认为你的类型应该与现实相符 - 防御性编程与你定义的类型相反是有异味的 - 但我也理解并非每个代码库都可以或应该以这种方式工作。
是的,TS运行的结构化类型模型使得“对象”情况变得更加复杂,因为“对象”类型不一定是“对象”。
有人可能会认为最“正确”的做法是不缩小类型 - 但这可能会让大多数不熟悉TS类型系统的人大吃一惊。
如果你把它当作一个对象来处理,那么它是基于这样一个假设:(在TS的大规模范围内)很可能在某些代码库中并不成立 - 这意味着你在惊讶不同的人群。
所以我想这并不能真正通过“不会让任何人感到惊讶的功能”测试,因为有些事情如果你不了解TS的类型系统可能会让人感到惊讶?

wfveoks0

wfveoks04#

我猜这并不能通过“不会让任何人感到惊讶的功能”测试,因为如果你不了解TS的类型系统,某些事情可能会让人感到惊讶?
我还会进一步说,即使你了解TS的类型系统,这里的结果仍然会看起来令人惊讶/不稳定,除非你真正以防御性的方式去思考,这是人们经常抱怨的不直观的行为。
我们甚至还没有提到"function"在几乎任何对象类型的结果中应该是什么,这将是一个进一步的混淆点。

相关问题