情况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”则不会。
答案 0 :(得分:2)
TypeScript提供了刷新的概念(也称为严格对象文字检查),可以更轻松地键入在结构上与类型兼容的检查对象文字。
按照上面的链接,对此主题的解释很清楚。
在这里,我将简要介绍您的情况。
// 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);
}
这一次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 }
那样,您将被迫遵守界面。并在尝试添加意外的额外数据时出现错误