microsoft / microsoft/TypeScript

FAQs: bivariance example is wrong

Đang mở
#45,196 5 bình luận 0 reaction 1 người được giao Xem trên GitHub

@RyanCavanaugh đang làm issue này rồi.

Từ ngày 5/8/2021.

Docs
Ngôn ngữ chính
Go
Star
111k
Fork
14.4k
Merge trung bình
1 ngày 19 giờ
Pull request đã merge (30 ngày)
117

Mô tả

Bug Report

the example provided here is not a clear example of bivariance:

function trainDog(d: Dog) { ... }
function cloneAnimal(source: Animal, done: (result: Animal) => void): void { ... }
let c = new Cat();

// Runtime error here occurs because we end up invoking 'trainDog' with a 'Cat'
cloneAnimal(c, trainDog);

this isn't really a problem with bivariance, and can be solved by simply using a generic on cloneAnimal:

function cloneAnimal<T extends Animal>(source: T, done: (result: T) => void) { ... }

we now correctly receive a compile error, even with all the strictness flags disabled

i would suggest using the following example instead:

class Animal {
    walk() { }
}

class Dog extends Animal {
    bark() { }
}

class Cat extends Animal {
    meow() { }
}

class List<T> {
    constructor(public values: T[]) {}
    add(value: T) {
        this.values.push(value)
    }
}

const cats: List<Cat> = new List([new Cat()])

const animals: List<Animal> = cats

animals.add(new Dog())

// runtime error, because the list of cats now has a dog in it
cats.values[1].meow()
🔎 Search Terms

faq bivariance

⏯ Playground Link

Playground link with relevant code

💻 Code
class Animal {
    walk() { }
}

class Dog extends Animal {
    bark() { }
}

class Cat extends Animal {
    meow() { }
}

declare function trainDog(d: Dog): void
declare function cloneAnimal(source: Animal, done: (result: Animal) => void): void
declare function cloneAnimalGeneric<T extends Animal>(source: T, done: (result: T) => void): void
let c = new Cat();

// Runtime error here occurs because we end up invoking 'trainDog' with a 'Cat'
cloneAnimal(c, trainDog);

// compile error: Argument of type '(d: Dog) => void' is not assignable to parameter of type '(result: Cat) => void'
cloneAnimalGeneric(c, trainDog);

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.