区分空对象类型和其他具体类型
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;
有没有一种方法可以定义一个具有所有可选属性的类型,但仍然可以区分 string
、number
和 boolean
等非对象类型?
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");
}
}
所有这些编译没有错误:
interface Empty { }
interface MaybeEmpty { a?: number; }
var one: Object = 20;
var two: Empty = 21;
var three: {} = 22;
var four: MaybeEmpty = 23;
有没有一种方法可以定义一个具有所有可选属性的类型,但仍然可以区分 string
、number
和 boolean
等非对象类型?
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");
}
}