【问题标题】:Discriminate between empty object type and other concrete types区分空对象类型和其他具体类型
【发布时间】:2015-01-24 05:54:24
【问题描述】:

所有这些都编译没有错误:

interface Empty { }
interface MaybeEmpty { a?: number; }

var one: Object = 20;
var two: Empty = 21;
var three: {} = 22;
var four: MaybeEmpty = 23;

有没有一种方法可以定义一个具有所有可选属性的类型,但仍然可以区分stringnumberboolean 等非对象类型?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    TS2.4+ 的更新,现在有 weak type detection,如果没有重叠的属性,它将阻止分配给所有可选属性类型,如 MaybeEmpty,因此现在不允许使用 var four: MaybeEmpty = 23


    TS2.2+ 的更新,现在有一个 object 类型,它专门排除了原语。使用花括号的类对象类型(如 {}{ a?: number })仍然与原语兼容,如下所述。


    原答案:

    没有。

    根本问题在于,当在需要对象的上下文(例如属性访问)中使用时,JavaScript 通常将原始值视为它们的对象类型等效项(String/Number/etc)。

    TypeScript 使用 “表观类型” 对此进行建模,其中原始类型的对象似乎具有其相应 Object 类型的成员。这是因为,直观地说,像这样的代码应该编译时不会出错:

    function fn(x: { toString(): string }) { /* ... */ }
    fn(32); // Should be OK because (32).toString() is OK
    fn('foo'); // Should be OK because ('foo').toString() is OK
    

    这是代码的一小步:

    function fn(x: { toString(): string; other?: whatever; }) { /* ... */ }
    fn(32); // Should be OK
    fn('foo'); // Should be OK
    

    这个代码的另一个小步骤:​​

    function fn(x: { other?: whatever; }) { /* ... */ }
    fn(32); // OK, I guess?
    fn('foo'); // OK, I guess?
    

    有一个issue on GitHub 跟踪一般问题,即具有所有可选属性的接口在将其分配 时实际上永远不是错误的来源。规范是一件非常困难的事情。

    【讨论】:

    • object 和弱类型检测更新了这个答案,希望你没问题。
    【解决方案2】:

    亡灵术。
    自己有这个问题。
    这在 TypeScript 2.2+ 中实际上是可能的。

    您需要在类型定义中添加 & 对象

    例如

    var varname: YourInterface & object = something;
    

    在你的情况下:

    interface Empty { }
    interface MaybeEmpty { a?: number; }
    interface MaybeEmptyAndMore { a?: number; [x:string]: any; }
    
    
    var one: Object = 20;
    var two: Empty = 21;
    var three: {} = 22;
    var four: MaybeEmpty & object = 23;
    var foura: MaybeEmpty & object = {};
    var fourb: MaybeEmpty & object = { a: "23"};
    var fourc: MaybeEmpty & object = { abc: "23"};
    var fourd: MaybeEmptyAndMore & object = { abc: "123", def: "456" };
    

    顺便说一句,如果可以是字符串或者接口(对象),那么:

    obj: string | YourInterface & object
    

    例如

    class Cookie
    {
        constructor(nameOrSettings: string | ICookieSettings  & object )
        {
            if(typeof(nameOrSettings)  === 'string')
            { do_something();}
            else if(typeof(nameOrSettings) === 'object')
            {
                 var obj:ICookieSettings = <ICookieSettings><any>nameOrSettings;
            }
            else throw TypeError("foo");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      相关资源
      最近更新 更多