2017-04-13 36 views
0

初始分配之後我有一個接口Base,哪些接口AB延伸,並且AB都有是獨特的並且在其他不存在的屬性。在我的代碼,我有一些數據,將根據類型而改變:指定變量的類型在打字稿

interface Base { 
    basicProperty: any, 
    basicProperty2: any 
} 

interface A extends Base { 
    aSpecificProperty: any 
} 

interface B extends Base { 
    bSpecificProperty: any 
} 

function(type): A | B { 
    const data: A | B = { 
    basicProperty: 1, 
    basicProperty2: 2 
    } 

    if (type === 'A') { 
    // Data should be type A 
    data.aSpecificProperty = 3; 
    } else if (type === 'B') { 
    // Data should be type B 
    data.bSpecificProperty = 3; 
    } 

    return data; 
} 

有沒有辦法做到這一點沒有打字稿抱怨不包含正確的屬性類型?或者,有沒有辦法將data的類型從A | B重新分配/指定爲AB

回答

0

有很多方法可以實現你想要的。如果你的回報是基於type: string說法,爲什麼不使用類似:

interface Base { } 
class A implements Base { name: string } 
class B implements Base { value: number } 

function fn(type): Base { 
    if (type == 'A') { 
    const data: A = { 
     name: 'abc' 
    } 
    //... 
    return data; 
    } 

    if (type == 'B') { 
    const data: B = { 
     value: 10 
    } 
    //... 
    return data; 
    } 
} 

我需要更多的信息,關於您的問題給出更好的答案,但是,因爲你有一個Base類如你所說,這樣的事情可以幫助你。

UPDATE

根據您的更新和評論,我會建議如下代碼:

interface Base { 
    basicProperty: any, 
    basicProperty2: any 
} 

interface A extends Base { 
    aSpecificProperty: any 
} 

interface B extends Base { 
    bSpecificProperty: any 
} 

function typeFactory<T extends Base>(obj: Base, ext: Partial<T>) { 
    return Object.assign(obj, ext) as T; 
} 

function myFn(type): A | B { 
    const data: Base = { 
    basicProperty: 1, 
    basicProperty2: 2 
    } 

    switch (type) { 
    case 'A': 
     return typeFactory<A>(data, { 
     aSpecificProperty: 3 
     }); 
    case 'B': 
     return typeFactory<B>(data, { 
     bSpecificProperty: 3 
     }); 
    } 
    // ... 
} 

參考有關Object.assign(...)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

+0

我更新的問題,使其多一點具體談談我的使用情況。 – josh

+0

好的,我明白了。讓我問你,關於如我所建議的那樣在'if' con塊中創建'data'對象,對你來說是一種選擇嗎?否則,你將需要聲明'data'作爲你的'Base'接口('data:Base'),你將需要使用'cast'操作來改變'if'條件中的類型。 – Diullei

+0

我在上面的例子中簡化了數據,但數據是一個大對象......所以如果我將數據複製到每個數據中,這將會造成很多重複。我實際上通過查看「cast」(我創建沒有類型的「基礎數據」,然後使用它們各自的類型爲A和B創建變量)並在if塊中分配,來分別計算出要執行的操作。那有意義嗎? – josh

0

你有沒有使用的typeof考慮運營商?

interface IBase { 
 
    name: string; 
 
    sayName(); 
 
    } 
 

 

 
class A implements IBase { 
 
    constructor(public name: string) { } 
 
    sayName() { 
 
     console.log(name); 
 
    } 
 

 
    onlyA() 
 
    { 
 
     console.log("I exist only in A"); 
 
    } 
 
} 
 

 
class B implements IBase { 
 
    constructor(public name: string) { } 
 
    sayName() { 
 
     console.log(name); 
 
    } 
 

 
    onlyB() 
 
    { 
 
     console.log("I exist only in B"); 
 
    } 
 
} 
 

 
function myFunc<T extends IBase>(arg: T) : any { 
 
    
 
    const data: T = arg; 
 

 
    if (typeof(data) === typeof(A)) { 
 
     // Data should be type A 
 
     data.sayName(); 
 
     let aObj: A = data as any; 
 
     aObj.onlyA(); 
 
    } else if (typeof(data) === typeof(B)) { 
 
     // Data should be type B 
 
     data.sayName(); 
 
     let bObj: B = data as any; 
 
     bObj.onlyB(); 
 
    } 
 

 
    return data; 
 
} 
 

 
let a = myFunc(new A("I am A")); 
 
let b = myFunc(new B("I am B")); 
 

 
a.onlyA(); 
 
b.onlyB();

這基本上讓通用函數檢查類型並返回任何類型的對象。

這是你在找什麼或我沒有按照正確的問題嗎?

根據您例如,它會看起來像

interface IBase{ 
 

 
} 
 

 
class A implements IBase { 
 

 
} 
 

 
class B implements IBase{ 
 

 
} 
 

 
function myFunc<T extends IBase>(type: T): A | B { 
 
    const data: A | B = { 
 

 
    } 
 

 
    if (typeof(type) === typeof(A)) { 
 
     // Data should be type A 
 
    } else if (typeof(type) === typeof(B)) { 
 
     // Data should be type B 
 
    } 
 

 
    return data; 
 
}