Bug报告
🔎 搜索词
- object
- 通用函数
- 参数
- 参数化类型
- 重命名
- 转到定义
- 查找引用
🕗 版本与回归信息
- 在所有我尝试的版本中,这种行为都是如此,我也查看了关于上下文类型的文章中的常见问题解答。
⏯ Playground链接
无
💻 代码
希望对象具有类型注解,以便语言服务器功能可以在对象属性上正确工作,例如“重命名”/“转到定义”/“查找引用”。
以下示例都有类型注解,但这些语言服务器功能不起作用。
这似乎是因为上下文类型没有传递给提供给通用函数的参数。
是否有可能改变这种行为,使上下文类型能够传递?特别是当参数是一个对象字面量表达式时。
declare const identity: <T>(x: T) => T;
type User = { name: string };
const value: User = identity({ name: "bob" });
正如您在这个演示中看到的,如果我们重命名一个属性,重命名不会传播。这是因为 TypeScript 似乎无法理解对象字面量表达式和类型之间的关系,尽管我们已经在对象定义附近提供了一个非常接近的类型注解。
Screen.Recording.2022-09-20.at.18.05.03.mov
一个经常出现的真实世界例子是当我们使用 O.some
函数时。
import * as O from "fp-ts/Option";
type User = { name: string };
const value: O.Option<User> = O.some({ name: "bob" });
另一个经常在使用 pipe
函数(如在 fp-ts
中定义的)时出现的真实世界例子是:
declare function pipe<A, B>(a: A, ab: (a: A) => B): B;
type User = { name: string };
declare const logName: (user: User) => void;
pipe({ name: "foo" }, logName);
8条答案
按热度按时间dohp0rv51#
这似乎是因为上下文类型没有流向提供给泛型函数的参数。
上下文类型确实流向;证明:
你描述的问题是否存在类型系统观察,还是只是 find all / rename 没有按预期工作?
h79rfbju2#
我错了——你是对的!
问题是find all / rename没有按预期工作吗?
只是这样。
出于兴趣,如果上下文类型确实如你所指出的那样流动,为什么find all / rename不起作用?我想
{ name: "bob" }
的值没有给定User
的类型——TypeScript只是检查它是否可以分配给上下文类型User
吗?vh0rcniy3#
你描述的问题是否有类型系统的观察?
实际上,我认为这可能是一个?
ddhy6vgd4#
这是一个不同的问题(我认为...),
identity
首先从其参数中推断出其返回类型,然后其返回类型最终可以分配给{ name: string, age?: number }
,因此没有多余的属性错误,因为到那时对象字面量不再被认为是“新鲜”的(即它正在检查函数的返回值,而不是直接的对象字面量)。上下文类型User
作为推断候选项的优先级可能低于您实际提供的参数。基本上,多余的属性检查不是正常类型检查流程的一部分,通常依赖于显式类型注解;让您让类型推断的情况通常会绕过它们。
cygmwpex5#
上下文类型化不会过度检查属性(可能令人惊讶)
1zmg4dgp6#
5cnsuln77#
感谢您的澄清和更新这个问题。
关于我描述的过度属性的行为,您有什么想法吗?这个是否也可以改变/修复?我怀疑这已经是一个其他问题了。
另外,但相关的是,我正在尝试编写一个lint规则来要求对象的类型注解。我的动机和我的工作进度可以在这里找到:typescript-eslint/typescript-eslint#5666 。我已经通过检查
ObjectLiteralExpression
是否有上下文类型并在没有的情况下报告一个lint错误取得了很好的进展,但在上面的场景中,我们将一个对象传递给一个泛型函数时,这种方法不起作用:似乎对象确实有一个上下文类型,但那个上下文类型似乎是从对象本身(而不是context)推断出来的。这是我目前为止所拥有的内容。您认为这是正确的吗?还是有另一种方法可以捕获这种情况?
mzsu5hc08#
这取决于你想要发生什么,但这似乎是正确的方法。