处理这样一种情况的正确方法是什么,你有两个足够相似的接口,你想通过同一个逻辑运行它们:
interface DescriptionItem {
Description: string;
Code: string;
}
interface NamedItem {
Name: string;
Code: string;
}
function MyLogic(i: DescriptionItem | NamedItem) {
var desc = (<DescriptionItem>i).Description || (<NamedItem>i).Name;
return i.Code + ' - ' + desc;
}
Run Code Online (Sandbox Code Playgroud)
这有效; 但是,我的问题是改善这var desc = ...条线.我有什么最好的选择?或者有没有更好的方法来处理Typescript中的这种情况?
我知道这个问题很老了,但我一直在解决同样的问题,因为我正在学习 | 之间的区别。和 & 在创建类型联合时。
有一些选项可以解决这个问题(这也是 linter 友好的)。最好的方法是在所有接口(窄接口)中使用鉴别器。
//First create a super-interface that have the discriminator
interface B
{
kind:'b1'|'b2' //define discriminator with all the posible values as string-literals (this is where the magic is)
}
interface B1 extends B
{
kind: 'b1' //now narrow the inherited interfaces literals down to a single
//after that add your interface specific fields
data1: string;
data: string;
}
interface B2 extends B
{
kind:'b2' //now narrow the inherited interfaces literals down to a single
//after that add your interface specific fields
data2: string;
data: string;
}
//lets initialize 1 B1 type by using the literal value of a B1 interface 'b1'
var b1: B1|B2 = {
kind:'b1',
data: 'Hello From Data',
data1:'Hello From Data1'
//typescript will not allow you to set data2 as this present a B1 interface
}
//and a B2 Type with the kind 'b2'
var b2: B1|B2 = {
kind: 'b2',
data: 'Hello From Data',
//typescript will not allow you to set data1 as this present a B2 interface
data2: 'Hello From Data2'
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用“in”关键字检查对象上的字段,但这可能会导致大量样板代码,因为每次更改界面时都必须更新它。
interface B1
{
data1: string;
data: string;
}
interface B2
{
data2: string;
data: string;
}
var b3: B1|B2 = {
data: 'Hello From Data',
data1:'Hello From Data1',
data2:'Hello From Data2'
}
console.log(b3.data); //this field is common in both interfaces and does not need a check
if('data1' in b3) //check if 'data1' is on object
{
console.log(b3.data1);
}
if('data2' in b3){
console.log(b3.data2); //check if 'data2' is on object
}
Run Code Online (Sandbox Code Playgroud)
TypeScript interfaces仅在编译时存在,因此您无法在运行时测试接口类型.您在问题中指定的代码很有意义,可能是您的最佳选择.
但是,如果您可以灵活地更改interfaces到classes,则可以使用TypeScript的类型保护来执行更优雅的类型检查:
class DescriptionItem {
Description: string;
Code: string;
}
class NamedItem {
Name: string;
Code: string;
}
function MyLogic(i: DescriptionItem | NamedItem) {
let desc: string;
if (i instanceof DescriptionItem) {
desc = i.Description;
} else {
desc = i.Name;
}
return i.Code + ' - ' + desc;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3194 次 |
| 最近记录: |