我正在try 重新组织打字字体中的一些字段,但遇到了一个错误.以下是我的代码的简化版本:

interface Test {
    data: string;
    where: string;
}

type TTA<T extends Test> = Pick<Omit<T, "data">, "where">;

我收到一个错误,显示为:Type '"where"' does not satisfy the constraint '"data" | Exclude<keyof T, "data">'.ts(2344).然而,如果我这样使用它,它工作得很好:

type TTB = Pick<Omit<Test, "data">, "where">;

有人能帮助我解决这个错误并解释为什么第一种方法没有按预期工作吗?

Typescript playground

推荐答案

您遇到了字体的设计限制,如第microsoft/TypeScript#53368节所述

问题在于

type TTA<T extends Test> = Pick<Omit<T, "data">, "where">;

Omit<T, "data">取决于判断generic类型Tconditional type.(The Omit utility type是用the Exclude utility type实现的,the Exclude utility type实现为条件类型.)而且这种类型对于类型判断器来说是出了名的难以分析.泛型条件类型对于编译器来说本质上是不透明的;它不能像人类那样计算不变量(另外,单词"Omit"是对人类的暗示,而不是对编译器).因此,尽管人类可能会推断,对于所有T extends Test,Omit<T, "data">必须包含where属性,因为T包含where属性,而Omit不会删除它,编译器只是放弃,无法验证这一点.


解决错误在某种程度上是一个主观问题,即决定如何让编译器相信该属性是可接受的:

// like this
type TTB<T extends Test> = Pick<Omit<T, "data"> & { where?: any }, "where">;

// or maybe like this
type LoosePick<T, K extends PropertyKey> = Pick<T, K & keyof T>
type TTC<T extends Test> = LoosePick<Omit<T, "data">, "where">;

// et cetera

Playground link to code

Typescript相关问答推荐

参数类型undefined不能分配给参数类型字符串|未定义

隐式键入脚本键映射使用

Vue SFC中的多个脚本块共享导入的符号

TypeScrip界面属性依赖于以前的属性-针对多种可能情况的简明解决方案

有没有一种方法可以确保类型的成员实际存在于TypeScript中的对象中?

跟踪深度路径时按条件提取嵌套类型

TypeScrip:使用Union ToInterval辅助对象,但保留子表达式

类型脚本-处理值或返回值的函数

TypeScrip-根据一个参数值验证另一个参数值

有没有办法传递泛型类型数组,以便推断每个元素的泛型类型?

当传递带有或不带有参数的函数作为组件props 时,我应该如何指定类型?

基于泛型的类型脚本修改类型

任何导航器都未处理有效负载为";params";:{";roomId";:";...";}}的导航操作

我可以使用JsDocs来澄清Typescript实用程序类型吗?

通过辅助函数获取嵌套属性时保留类型

使用 fp-ts 时如何使用 TypeScript 序列化任务执行?

对于通过 Axios 获取的数据数组,属性map在类型never上不存在

如何让 Promise 将它调用的重载函数的类型转发给它自己的调用者?

对象可能未定义(通用)

如何使用 TypeScript 接口中第一个属性的值定义第二个属性