区分空对象类型和其他具体类型

Discriminate between empty object type and other concrete types

所有这些编译没有错误:

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

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

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

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


TS2.2+ 更新,现在有一个 object 类型专门排除基元。像 {}{ a?: number } 这样使用大括号的类对象类型仍然与基元兼容,如下所述。


原回答:

没有

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

TypeScript 使用“表观类型” 对此进行建模,其中原始类型的对象似乎具有其相应对象类型的成员。这是因为,直觉上,像这样的代码 应该 编译无误:

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 跟踪一般问题,即在将 分配给 时,具有所有可选属性的接口实际上永远不会是错误的来源。这是一件很难规范的事情。

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

您需要将 & object 添加到您的类型定义中

例如

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");
    }
}