2017-03-28 157 views
3

我有一个函数(func)的类(MyClass)与可选参数。可选参数(MyInterface)的类型只有可选属性。typescript可选参数类型检查

我希望编译器错误,当我用像一个数字原语调用foo。但事实并非如此。这是为什么?有没有办法告诉类型系统将其标记为错误?

interface MyInterface { 
    foo?: string 
} 

class MyClass { 
    func(b?: MyInterface) : void {} 
} 

let c = new MyClass(); 
c.func(); 
c.func({ foo: 'bar' }); 
c.func({ foo: 30 });  // compiler error: OK 
c.func({}); 
c.func(60);    // No compiler error: Not what I expect 

回答

2

出现这种情况的原因是,number{}兼容。 (例如,想象一种类型为{toFixed: (n: number) => string}的参数,该参数也与number兼容)。

你也可以这样想:你可以用数字做任何事情,你可以用{foo?: string}

+0

听起来像鸭子打字。 TypeScript是否有类型的鸭子打字?与其中空类与另一空类不同的java不同。 – stefku

+0

是的,对象不需要实际地明确实现一个接口来属于该接口。属性只需要匹配。请注意,使用'MyInterface'要求,您将无法将'60'视为'MyClass.prototype.func'中的数字。 –

0

让我们介绍一些肮脏的console.log调试:

interface MyInterface { 
    foo?: string 
} 

class MyClass { 
    func(b?: MyInterface): void { 
     console.log(`b:${b}`); 
     if (b != undefined) { 
      console.log(`b.foo:${b.foo}`); 
     } 
    } 
} 

let c = new MyClass(); 
c.func(); 
c.func({ foo: 'bar' }); 
c.func({ foo: 30 });  // compiler error: OK 
c.func({}); 
c.func(60);    // No compiler error: Not what I expect 

结果是:

b:undefined 

b:[object Object] 
b.foo:bar 

b:[object Object] 
b.foo:30 

b:[object Object] 
b.foo:undefined 

b:60 
b.foo:undefined 

让我们专注于过去的两个结果。

MyInterface只有foo参数,而且它是可选的。所以实际上任何类型的都是MyInterface。这就是为什么参数b的值为60. b在这种情况下的类型为MyInterface没有可选的foo成员。

如果您从foo成员中删除可选运算符,那么编译器将抛出异常。如果您向MyInterface添加附加的非可选参数,它也会这样做。

也许它似乎违反直觉,但事实并非如此。在你提交的表格中,MyInterface没有定义任何内容。你要求编译器防止输入有foo参数......或者没有它。那为什么要检查输入是否为object