[英]Pattern matching switch statements
假設我有返回動物信息的 API。 然而,json 有效載荷對於每種動物來說差異很大,即使許多屬性是共同的和強制性的。
我想為這些不同的動物中的每一種都“強輸入”typescript class,這樣我的代碼就不會變得一團糟。 每只動物都需要非常獨特和特定的處理方式!
這樣做的正確方法是什么? 基本上我想完成這樣的事情:
interface Animal {
Name: string;
Weight: number;
}
interface Insect extends Animal {
AmountOfEyes: number;
}
interface Bird extends Animal {
PlumageColor : string;
}
function OnlyForBirds(bird: Bird)
{
// do something birdly
}
function OnlyForInsects(insect: Insect)
{
// do something creepy
}
function GetAnimal(animalId: string) : Promise<Animal>
{
const uri = `${baseURL}/${animalId}`;
// fetches the json response body from http request
const result = await get<any>(uri);
switch(animal.Name)
{
case 'Insect':
return result as Insect;
case ...
...
}
// throw unhandled
}
function ProcessAnimal(animalId:string) : Promise
{
let animal = await GetAnimal(animalId);
// how do I do this now? Can't I use something over tye interface
// types instead of using the .Name and casting again?
// is there any advisable standard I can use?
if(animal is a bird){
OnlyForBirds(bird)
}
else if(animal is an insect){
OnlyForInsects(insect)
}
}
任何建議,包括不使用這樣的界面,都值得贊賞。
對於您的用例,您發布的答案可能是最好的解決方案。 我只是想用不同的方法來插話。 如果您想擁有多層 inheritance,您的解決方案開始崩潰,其中Duck
擴展了Bird
。 如果要查找Animal
是否與基本Bird
接口匹配,可以定義自定義類型保護function 來查看 object 的屬性以查看它是否具有PlumageColor
。 如果是這樣,那么 typescript 知道可以將其用作Bird
。
這是基本版本。 我們說animal
有一個可選的屬性PlumageColor
以便我們可以無錯誤地訪問它,即使它是undefined
。 然后我們檢查PlumageColor
是否已定義並且它是一個string
。
const isBird = (animal: Animal & {PlumageColor?: any}): animal is Bird => {
return typeof animal.PlumageColor === "string";
}
這個帶有generics的版本更好,因為它斷言animal
是Bird
同時還保留了已經知道的關於animal
的任何其他類型信息。
const isBird = <T extends Animal & {PlumageColor?: any}>(animal: T): animal is T & Bird => {
return typeof animal.PlumageColor === "string";
}
我想到了。 一些深邃的黑暗魔法。 在基本接口中定義一個枚舉屬性。 每個新的不同類型的 class,或在這種情況下為動物,都為自己分配這些屬性之一。 打開這個屬性,在開關中你有你輸入的動物
enum AnimalType {
Insect = "Insect",
Bird = "Bird"
}
interface Animal {
Type: AnimalType;
Weight: number;
}
interface Insect extends Animal {
Type: AnimalType.Insect; // MAGIC BREWING
AmountOfEyes: number;
}
interface Bird extends Animal {
Type: AnimalType.Bird; // MAGIC BREWING
PlumageColor : string;
}
function OnlyForBirds(bird: Bird)
{
// do something birdly
}
function OnlyForInsects(insect: Insect)
{
// do something creepy
}
function GetAnimal(animalId: string) : Promise<Animal>
{
const uri = `${baseURL}/${animalId}`;
// fetches the json response body from http request
const result = await get<any>(uri);
switch(animal.Type)
{
case 'Insect':
return result as Insect;
case ...
...
}
// throw unhandled
}
function ProcessAnimal(animalId:string) : Promise
{
let animal = await GetAnimal(animalId);
switch(animal.AnimalType){
case AnimalType.Insect:
OnlyForInsects(animal); // within this case clause, animal is typed as an Insect! MAGIC!
break;
case AnimalType.Bird:
OnlyForBirds(animal); // within this case clause, animal is typed as an bird! Go free little bird!
break;
default:
// throw
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.