問題
我想定義一個人的寵物是可以延伸 Animal的,而不僅僅是Animal:
interface Person {
name: string
pet: extends Animal //I'm looking for something that would work here
}
我試過的
假設我們有這些介面:
interface Animal {
name: string
}
interface Fish extends Animal {
swim: () => void
}
interface Bird extends Animal {
fly: () => void
}
1.使用父型別
我知道我可以做到:
interface Person {
name: string
pet: Animal // Not what I want, because it needs to be only things that extend Animal
}
但這會阻礙推理。因為如果pet不是 a Fish,它應該是 a Bird。但是這樣它也可以是一個普通的Animal.
2.聯合型別
要僅使用 extends 型別Animal,我可以使用聯合型別自己選擇它們:
interface Person {
name: string
pet: Fish | Bird // Not what I want, because I would need to update it with new animals
}
但是如果我想創造更多的動物型別,我就必須Person每次都更新。
例如,如果我添加:
interface Mole extends Animal {
dig: () => void
}
我想通過更改為Person自動接受Mole作為寵物而不明確添加它。pet: Fish | Birdpet: Fish | Bird | Mole
概括
我正在尋找一種接受任何擴展 Animal的方法,但不接受父母 Animal本身,而不必每次有新動物出現時都更新它。我怎樣才能在打字稿中做到這一點?
筆記
我不需要Animal作為介面存在,但如果它可以保持介面就好了。
uj5u.com熱心網友回復:
這就是泛型出現的地方:
interface Person<T extends Animal> {
name: string
pet: T
}
let personWithBirdPet: Person<Bird>;
let personWithFishPet: Person<Fish>;
let personWithMolePet: Person<Mole>;
泛型有點像“型別引數”,就像您可以為函式定義“值引數”一樣,function(foo, bar) {}我們可以為大多數型別結構(包括函式function<A, B>(foo: A, bar: B) {}和介面)定義稱為泛型的“型別引數”,如您所見多于)。
使用泛型時,我們可以通過使用extends關鍵字對泛型應用約束。例如function<A extends number>(value: A) {},與寫作幾乎相同function(value: number) {}。使用泛型的版本更強大,但也更冗長。在這個簡單的function例子中,使用泛型將是矯枉過正。但是,在您的interface情況下,使用泛型正是您所需要的。
記住鴨子打字
由于 typescript 是鴨式的(如果它像鴨子一樣走路和像鴨子一樣說話,那么它就是鴨子)。您可能會遇到一些需要注意的意外行為。
例如,您可以讓一個擁有普通動物的人作為寵物:
let personWithGenericPet: Person<Animal>;
..或者你可以讓一個人的寵物不“延伸”動物,但看起來像動物:
let personWithStrangePet: Person<{ name: 'bob' }>;
..說起來,aPerson長得像動物,所以你可以養一個人和一個人作為寵物:
let personWithPersonPet: Person<Person<Animal>>;
這些不是泛型引起的問題,而是 typescript 作業方式的核心問題。
操場
uj5u.com熱心網友回復:
像這樣的作業嗎?
interface Person<T extends Animal> {
name: string;
pet: T;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/414098.html
標籤:
