Generic <A>ใน TypeScript บางทีก็ส่ง <B> ไปแทนได้

คีร์เวิร์ด คือ TypeScript type is structural compatible, not nominal compatible

ตัวอย่างนี้ C<B> สามารถส่งเข้าไปในฟังก์ชั่นที่รับ C<A> ได้ เนื่องจากคลาส C ซึ่งเป็น generic class ไม่มีการดึง type parameter มาใช้ คือ มี value : string ซึ่งไม่เกี่ยวข้องอะไรกับ type parameter <T>

interface A { a : string }
interface B { b : number }
class C<T> { value: string }
function fun1(input: C<A>) { }
fun1(new C<A>()); // ok
fun1(new C<B>()); // ok

C<A> และ C<B> ด้านบน ใช้แทนกันได้เนื่องจากคุณสมบัติ structural compatibility คือ ทั้ง new C<A> และ new C<B> เมื่อแปลงออกมาจะได้ { value: string } ทั้งคู่

ส่วนในกรณีที่คลาส C มีการอ้างอิง type parameter <T> เช่น นำมาสร้างฟิลด์ value: T กรณีนี้ จะมองว่า T ที่ส่งเข้ามาในฟังก์ชั่นจะมีผลกับโปรแกรม ทำให้ C<B> ใช้แทน C<A> ไม่ได้

interface A { a : string }
interface B { b : number }
class D<T> { value: T }
function fun2(input: D<A>) { }
fun2(new D<A>()); // ok
// Argument of type D<B> is not assignable
// to parameter of type D<A>
fun2(new D<B>()); // error

จากโค้ดด้านบน new C<A> จะได้ { value: A } ส่วน new C<B> จะได้ { value: B } ซึ่ง {value : A } != { value : B } คือ structure ของ object ไม่เหมือนกันหรือไม่ compatible กันนั่นเอง

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.