当接口中的所有属性都是可选的时,为什么在Typescript中允许多余的属性?

时间:2019-12-07 16:49:55

标签: typescript

在以下代码中...

primesList

为什么在调用primesList时将interface Options { allowed?: string; } function test(options: Options) { return options; } const options = { allowed: 'allowed', notAllowed: 'notAllowed', }; test(options); // does not throw an error 添加到notAllowed时不会在Typescript中引发错误?

我该怎么写,以免多余的属性?

编辑1 ...

如果我将Typescript重写为options,可以使Typescript引发错误。

但是,因为我已指定函数中的options参数应该为Options类型,所以typescript不应该推断吗?

如果没有,打字稿尝试传递test(options)时不应该抛出错误吗?

否则,这对于其他开发人员将自己的对象传递到const options: Options = {...};函数中不是很有用。

编辑2 ...

我想要这样做的原因是我不想让开发人员拼写错误的属性。例如,我希望他们能够提供const object = {...};属性,并禁止test属性。当它们在include函数中作为参数传递对象变量(而不是对象文字)时,使这种情况发生的唯一方法是在includes接口{{1} }或类似的东西?

3 个答案:

答案 0 :(得分:1)

  

我该怎么写,以免多余的属性?

不能。 Typescript继承了JavaScript的duck typing,并且鸭子还是鸭子,即使鸭子发出不同的羽毛也很容易

或者换句话说:options内部的对象是Options对象,因为它具有Options所需的所有属性(无)。

答案 1 :(得分:1)

问题在于TypeScript确实没有exact types,其中属性仅限于显式声明的属性。您需要的Excess property checking仅在使用新鲜对象文字的特定情况下发生。

尝试解决此问题的一种方法是使您的test()函数具有通用性,使其在注意到额外属性的情况下无法编译。 linked duplicate question的答案说明了它是如何工作的。观察:

type Exactly<T, U> = T & Record<Exclude<keyof U, keyof T>, never>;
function test<T extends Exactly<Options, T>>(options: T) {
    return options;
}

const okay = { allowed: "okay" };
test(okay); // no error

const excess = {
    allowed: 'allowed',
    notAllowed: 'notAllowed',
};
test(excess); // error

好的,希望能有所帮助;祝你好运!

Link to code

答案 2 :(得分:0)

如果您要构建测试函数供其他开发人员稍后使用,则最好不要在参数类型输入中使用接口,因为除非将对象传递给test()函数之前将其键入,否则它将不起作用。最好的做法是使用可选参数:

function test(allowed?: string) {
  return { allowed };
}

const options = {
  allowed: 'allowed',
  notAllowed: 'notAllowed',
};

test(); //works fine
test(options.allowed); //works fine
test(options.allowed, options.disallowed);  //error