如果返回类型是嵌套对象,Typescript 将无法检查返回类型。考虑下面的代码,即使函数 A 中的结果变量与输出类型明显不匹配,Typescript 也不会发出错误。
interface Input {
a: string;
b: number;
}
interface Output {
c: Omit<Input, 'a'>;
d: string;
}
function A(input: Input): Output {
const result = { c: {a: 'aaa', b: 3}, d: 'okay' };
// Expect to have an error since the result is not matched to Output
// but there's not errors
return result;
}
function B(input: Input): Output {
const result = "{ c: {a: 'aaa', b: 3}, d: 'okay' }";
// Work as expected
return result;
}
// But access a property will give us error.
const test = A({ a: 'a', b: 3 });
test.c.a
知道为什么会这样吗?
如果我们明确告诉 Typescript const result: Output = ...
,它会给我们错误。但我不确定这是否是一个好习惯。还有其他方法可以让它按预期工作吗?
答案 0 :(得分:1)
知道为什么会这样吗?
如果我们明确告诉 Typescript const result: Output = ...
,它会给我们错误....
TypeScript 对对象文字应用比对其他表达式(包括变量引用)更严格的类型检查。在这种情况下,当您为 result
显式提供类型时,“更严格”的部分是 excess property check。¹ 这是一个实用检查,因为通常这是程序员错误,但在一般情况下 case 多余的属性没问题(因为对象的形状仍然匹配目标类型,它只是一个子类型,因为它有更多的属性)。
如果直接返回也会报错:
function A(input: Input): Output {
return { c: {a: 'aaa', b: 3}, d: 'okay' };
}
虽然(主观上)我通常更喜欢你的原始代码,因为它更容易调试。
这在很大程度上是风格问题,但我会尽可能通过将其作为一般做法来解决问题:
function A(input: Input) {
// ^−−−− No return type annotation
const result: Output = { c: {a: 'aaa', b: 3}, d: 'okay' };
// ^−−−−−−−−−− Explicit type
return result; // <−−−−−− TypeScript infers return type
}
请注意,函数的返回类型仍然是 Output
,只是 TypeScript 是从 return
推断出来的,而不是我们在两个地方明确指定它。
¹ 当我在 2021 年 4 月写这篇文章时,TypeScript 文档正在经历一次重大重写,链接的页面被列为“已弃用”,并添加了“新页面”的新内容,但新页面还没有描述多余的财产检查。希望这能尽快解决。