这个想法是强制不使用传递给函数的对象中的某些字段,并且您可以使用其他任何内容(这就是为什么extends)
type ForbiddenFields = 'a' | 'b' | 'c';
type Data = { [K in ForbiddenFields]?: never };
function foobar<T extends Data>(data: T): void {
//...
}
const obj = { x: 1, y: 2 };
foobar(obj); // Type '{ x: 1, y: 2 }' has no properties in common with type Data
Run Code Online (Sandbox Code Playgroud)
为什么我得到
类型 '{ x: 1, y: 2 }' 与 Data 类型没有共同的属性
如果函数只是期望一个扩展的 Data对象,那么这不是等于说<T extends {}>但只是强制执行如果ForbiddenField指定了 a 则它必须存在never- 因此,不能存在吗?
这与TypeScript 2.4 中引入的弱类型检测发生冲突。由于Data的属性都是可选 的,因此编译器将其视为“弱类型”,因此与任何其他类型不兼容,除非至少有一个重叠属性。就像对象文字的多余属性检测一样,这并不是真正的类型系统健全性功能;它更像是一个 linter 规则,可以阻止它认为可能是错误的事情。
弱类型检测的发行说明说:
由于这是一个重大更改,您可能需要了解与严格对象文字检查相同的解决方法:
- 如果属性确实存在,则声明它们。
- 向弱类型添加索引签名(即
[propName: string]: {})。- 使用类型断言(即
opts as Options)。
我们可以使用第二个建议并添加字符串索引签名;因为我们不想限制任何其他属性,所以我们可能应该将值设置为类型(any因为即使类型安全unknown最终也会排除没有索引签名的接口类型,这是我们不想做的)。它可能看起来像这样:
interface AnyData extends Data {
[k: string]: any;
}
function foobar<T extends AnyData>(data: T): void {
//...
}
Run Code Online (Sandbox Code Playgroud)
您可以验证事情是否按预期运行:
const obj = { x: 1, y: 2 };
foobar(obj); // okay
const obj2 = { x: 1, y: 2, c: 3 };
foobar(obj2); // error! Types of property 'c' are incompatible.
interface Baz {
x: 1,
y: 2
}
declare const baz: Baz;
foobar(baz); // okay
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
181 次 |
| 最近记录: |