gpt4 book ai didi

typescript - 防止回调返回类型在 TypeScript 中包含其他属性

转载 作者:搜寻专家 更新时间:2023-10-30 21:32:33 26 4
gpt4 key购买 nike

假设我有一个接口(interface) Foo 和一个函数 bar,它接受一个返回 Foo 的回调。

interface Foo {
foo: string;
}

function bar(callback: () => Foo): Foo {
return callback();
}

当我调用它时,如果我向返回值添加 foo 以外的属性,编译器不会抛出错误。

// throws an error as expected
const x: Foo = { foo: 'abc', baz: 'def' };

// does not throw an error
const y = bar(() => ({ foo: 'abc', baz: 'def' }));

如何确保该对象没有除 Foo 中指定的属性外的其他属性?我试过使用 type 而不是 interface 得到相同的结果。这是 TypeScript playground .

最佳答案

Excess property checking仅在特定情况下才会发生,而您已经找到了不会发生的情况。 TypeScript 中的类型(包括 Foo 等接口(interface))是开放式和可扩展的;你可以定义一个接口(interface),比如

interface Baz extends Foo {
baz: string;
}

并在 bar() 回调中返回一个 Baz,它是一个有效的 Foo:

const baz: Baz = { foo: "abc", baz: "def" };
const foo: Foo = baz; // no error
const z = bar(() => baz); // no error...

TypeScript 没有对应于 exactly 的具体类型Foo 没有额外的属性。但是,可以使用 generic constraint表示“没有已知额外属性的Foo”。请注意“已知”警告,那里...稍后会出现:

function bar<
F extends Foo & { [K in keyof F]: K extends keyof Foo ? Foo[K] : never }
>(callback: () => F): Foo {
return callback();
}

在这里,我将 bar() 变成了一个通用函数,它接受类型为 () => F 的回调,其中 F被限制为 Foo,以及一个映射的条件类型。此映射类型采用任何已知的额外键并将属性类型更改为 never,这是不可能的。例如,如果 FBaz,则约束是 Foo & { foo: string, baz: never }。由于 Baz 不扩展 { foo: string, baz: never },如果您尝试调用 bar(),您将收到错误消息在已知返回 Baz 的函数上:

const y = bar(() => ({ foo: "abc", baz: "def" })); // error, generic constraint failed
// -----------------------------> ~~~
// "string" is not assignable to "never"

const z = bar(() => baz); // error! "string" is not assignable to "never"
// ---------------> ~~~

这至少会阻止人们返回带有额外属性的对象字面量。


然而,这并不是一个完美的解决方案。之前的变量 foo 被注释为 Foo 类型,但被初始化为 Baz 类型的值。编译器只知道或关心 fooFoo 类型。它完全忘记了 foo 也是 Baz 类型。因此它不知道 foo 有一个 "baz" 属性,并且不会阻止这个:

const oops = bar(() => foo); // still no error... 
// foo has a "baz" property but the compiler forgot
// no way around this in TypeScript, sorry

恐怕除了运行时检查之外,没有什么可做的。如果你真的想在 TypeScript 中看到确切的类型,你可能想转到 relevant GitHub issue并给它一个👍。但也许上述解决方案足以满足您的用例。

好吧;希望有所帮助。祝你好运!

Link to code

关于typescript - 防止回调返回类型在 TypeScript 中包含其他属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57316443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com