Typescript 无法检查函数返回类型的嵌套对象

Posted

技术标签:

【中文标题】Typescript 无法检查函数返回类型的嵌套对象【英文标题】:Typescript fails to check nested object on function return type 【发布时间】:2021-07-16 12:16:55 【问题描述】:

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

Playground here.

知道为什么会这样吗?

如果我们明确告诉 Typescript const result: Output = ...,它会给我们错误。但我不确定这是否是一个好习惯。还有其他方法可以使其按预期工作吗?

【问题讨论】:

为什么const result = " c: a: 'aaa', b: 3, d: 'okay' "; 中的值有引号? (我敢肯定你一秒钟前没有,是吗……?) 这里是测试typescript是否进行类型检查。在函数 A 中,我返回一个对象,在函数 B 中,我返回一个字符串。 Typescript 确实在函数 B 中显示错误,因为 String 与输出类型不匹配。但是当涉及到一个对象时,Typescript 并没有显示任何错误。 是的,我把AB 弄糊涂了。 我的错。它可以以更清晰的方式命名哈哈 【参考方案1】:

知道为什么会这样吗?

如果我们明确告诉 Typescript const result: Output = ...,它会给我们错误....

TypeScript 对对象 literals 应用比对其他表达式(包括变量引用)更严格的类型检查。在这种情况下,当您显式为 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 推断出来的,而不是我们在两个地方明确指定它。

Playground link


¹ 当我在 2021 年 4 月写这篇文章时,TypeScript 文档正在经历重大改写,链接页面被列为“已弃用”,并带有“新页面”的新增内容,但新页面尚未描述过多的财产检查。希望尽快解决。

【讨论】:

啊,明白了!非常感谢您为我指出“多余的财产检查”。我不知道这一点。另外,感谢您提出的解决方案。非常有帮助。谢谢!!

以上是关于Typescript 无法检查函数返回类型的嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript:推断嵌套联合类型的类型

TypeScript--泛型

TypeScript--泛型

TypeScript类型检查机制

在 Typescript 中处理嵌套的可能为空的值

TypeScript类型检查机制