Typescript函数接受不带错误的正确参数

时间:2019-11-28 10:20:33

标签: typescript

情况1:将“ randomKey”传递给doMethod时未检测到错误。

interface Options {
 bar: string;
 foo?: number;
}

function doMethod(options: Options) {
 console.log(options);
}


const options = {
 bar: 'bar',
 foo: 123,
 randomKey: 231,
}
doMethod(options); // No errors appear!
console.log(options);

情况2:仅在将选项直接传递到函数中之后,才会出现错误

interface Options {
 bar: string;
 foo?: number;
}

function doMethod(options: Options) {
 console.log(options);
}

doMethod({
 bar: 'bar',
 foo: 123,
 randomKey: 231, // ERROR: "Object literal may only specify known properties, and 'randomKey' does not exist in type 'Options'."
});

console.log(options); // In this scenario, I cannot console log options

很难找到无声错误。例如,您可以很容易地拼错一个单词,并且事情可能不会如您所愿的发生。

当您拼写错误的“ foo”(如“ fooo”)时会发生什么?静默错误仍然会发生。您希望“ foo”会触发某些内容,但是在这种情况下,如果拼写为“ fooo”则不会。

2 个答案:

答案 0 :(得分:2)

  

TypeScript提供了刷新的概念(也称为严格对象文字检查),可以更轻松地键入在结构上与类型兼容的检查对象文字。

-来源TypeScript Deep Dive

按照上面的链接,对此主题的解释很清楚。

在这里,我将简要介绍您的情况。

// case 1: no error
const options = { bar: 'bar', foo: 123, randomKey: 231 };
doMethod(options);

// case 2: error
doMethod({ bar: 'bar', foo: 123, randomKey: 231 });

在运行时JavaScript中,两个用例都应该起作用。的确如此,因为JS是弱类型的,对象中的多余键在运行时不会造成损害。

返回TS,您指定doMethod(options)将接受形状为{ bar: string; foo?: number }的选项。这说明您对doMethod输入的最低要求。输入额外的键?没问题,这就是JS的工作方式。

然后,为什么世界上第二种情况下TS会向您抛出错误?

因为TS希望您知道多余的randomKey不必要!即使没有害处。

这是新鲜度概念背后的想法。一个模拟将是:

function add(a: number, b: number) { return a + b };

add(1, 2, 3); // TS Error

尽管在JS运行时中,该用法仍然有效,但您可能并不意味着那样。因此TS会提前警告您。


要回答问题的第二部分,如果只想保留对象的新鲜度,怎么办?如果要严格检查输入的确切形状怎么办?有一个缺点的解决方案:

type ExactShape<T, R> = T extends R
  ? Required<R> extends T
    ? T
    : never
  : never

function doMethod<T>(options: ExactShape<T, Options>) {
   console.log(options);
}

TypeScript Playground现场演示

这一次TS将如您所愿地引发错误。但是缺点是,当鼠标悬停在错误上时,它将不再告诉有用的信息您为什么输入错误。

答案 1 :(得分:-1)

没问题。这是正常行为。将接口视为提供数据的承诺。

重要的是要记住,一天结束时将打字稿编译为普通的javascipt。

只要您提供接口的所有数据,所提供的实际对象是否包含额外的信息都没有关系。

很好的例子是

interface Options {
 bar: string;
 foo?: number;
 randomKey: number
}

const doMethod =(options: Options): any=> {
 console.log(options);
}


const options = {
 bar: 'bar',
 foo: 123
}
doMethod(options); ** error appears!**
console.log(options);

要获得更好的类型安全体验,您可能还希望对对象使用接口。

const options: Options = { bar: 'bar', foo: 123 } 

那样,您将被迫遵守界面。并在尝试添加意外的额外数据时出现错误