网站搜索

TypeScript 在使用对象解析 promise 时允许冗余的键


你能帮我理解为什么 Typescript 在这里不报错吗:

type Test = Promise<{a: number}>;
const test: Test = Promise.resolve({a: 1, something: 'wrong'}); // no error

但是在这里

type Test2 = {a: number};
const test2: Test2 = {a: 1, something: 'wrong'}; // error 2322, ok

有什么办法让我让它在 Promise 上抛出类似的错误吗?

在不同版本的 TypeScript 上尝试过,包括最新版本,并启用了严格类型。尝试过用 new Promise 替代 Promise.resolve。都没有效果。可以看一下 Playground。

提前谢谢你!

答案#1

TypeScript 只在非常有限的情况下进行额外属性检查(将对象字面量直接赋值给类型化变量,从函数返回对象字面量;详情见此处),因为从类型系统的角度来看,这些额外属性是可以的(它们只是意味着该实例是具有更多信息的类型的子类型),但在你赋值的对象字面量上出现它们通常是程序员的错误。否则它不会进行此检查,因为在一般情况下,这可能并不是错误(只是,再次说明,是一个子类型)。

你可以通过给 Promise.resolve 提供一个类型参数来触发多余属性检查(playground 链接)(感谢 jcalz!):

const test = Promise.resolve<{a: number}>({a: 1, something: 'wrong'});
//                                               ^^^^^^^^^^^^^^^^^^−− Argument of type '{ a: number; something: string; }' is not assignable to parameter of type '{ a: number; } | PromiseLike<{ a: number; }>'

在这种情况下,TypeScript 将会推断 test 的类型为 Promise<{a: number}>(例如,你的 Test 类型)。

你还可以检查 async 函数的返回值(游乐场链接):

type Test = Promise<{a: number}>;
async function asyncExample(a: number): Test {
    return {a, extra: true}; // Type '{ a: number; extra: boolean; }' is not assignable to type '{ a: number; }'
}

...所以如果你能使用 async 函数而不是显式的 Promise 语法,你可能能够简化这些检查。