yazma - Parametreye bağlı olarak Typescript dönüş tipi


Bir parametre olarak boolean türünde bir değer alan ve giriş değerine bağlı olarak iki türden birini döndüren bir fonksiyon yazmaya çalışıyorum. İki yaklaşım buldum:

function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
    if (x) {
        return 3;
    } else {
        return "string";
    }
}

Burada, TypeScript Type '3'/'"string"' türü 'B extends true ? number : string' türüne atanamaz. diyor.

Benim diğer yaklaşımım şöyle görünüyor:

function dependsOnParameter(x: true): number;
function dependsOnParameter(x: false): string;
function dependsOnParameter(x: boolean): number | string {
    if (x) {
        return 3;
    } else {
        return "string";
    }
}

Bu derleniyor; ancak, eğer kendi fonksiyonumu kullanmayı denersem:

function calling(x: boolean) {
    dependsOnParameter(x);
}

Ben boolean türündeki argüman, false türündeki parametreye atanamaz hatasını alıyorum.

any kullanmadan istediğimi başarmanın bir yolu var mı?

Cevap #1

Her iki yaklaşım da geçerlidir. Fonksiyonunuz dönüşte koşullu tipler kullanıyorsa, tür onayları kullanması gerekecektir, çünkü TypeScript, serbest bir tür parametresi içerdiğinden dolayı koşullu tipi anlamaya çalışmayacaktır:

function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
    if (x) {
        return 3 as any;
    } else {
        return "string"as any;
    }
}

Bu yaklaşım, kaçınmak istediğiniz any öğesini kullanır.

Son imzayı sadece kopyalayarak, tür atamalarına başvurmadan çalıştırabileceğimiz ikinci yaklaşım:

function dependsOnParameter(x: true): number;
function dependsOnParameter(x: false): string;
function dependsOnParameter(x: boolean): number | string
function dependsOnParameter(x: boolean): number | string {
    if (x) {
        return 3;
    } else {
        return "string";
    }
}

function calling(x: boolean) {
    dependsOnParameter(x); // returns number| string
    dependsOnParameter(true); // returns number
    dependsOnParameter(false); // returns string
}

Son imza uygulama imzasıdır ve halka açık değildir. Onu çoğaltarak erişilebilir hale getirebilirsiniz. Derleyici, iki aşırı yükleme ile true/false’yi birleştirip dönüş tipinin string|number olduğunu belirleyecek kadar akıllı değildir.

Düzenle

Daha az imza için iki yaklaşımı da birleştirebiliriz:

function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string 
function dependsOnParameter(x: boolean): number | string{
    if (x) {
        return 3;
    } else {
        return "string";
    }
}

Cevap #2

Bu bir yol:

function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
    return (x === true ? 3 : "string") as B extends true ? number : string;
}

Burada, koşulun kendisi (B extends true ? number : string) bir tür olarak kabul edilir. Bu türe Koşullu Tür denir.

İlgili makaleler