Typescript: genel koşullu tipler hatası


TS'de koşullu tipler hakkında daha fazla bilgi edinmeye çalışıyorum ve küçük bir meydan okuma olarak, bir tür genel haritalayıcı yazmaya karar verdim. Ama bir hata ile takıldım

Yapmam gereken şey:

  • createMapper fonksiyonuna bir eşleyici (mapper) geçirmeniz gerekir;
  • createMapper’den, girdi özelliği bir değer veya değerler dizisi alabilen bir fonksiyon döner;
  • Bir değer geçtikten sonra TS derleyicisi, bir işlevden hangi türün döndürüldüğünü açıkça anlamalıdır;

şunun gibi bir şey:

type MapI = { abc: 123 };
const mapI: MapI = { abc: 123 };

const mappedArray = mapps<MapI, MapI>((m) => m)(Array(3).fill(mapI));
console.log(mappedArray.length); // no errors, compiler understands that it is an array;

const mappedValue = mapps<MapI, MapI>((m) => m)(mapI);
console.log(mappedValue.abc); // no errors, compiler understands that it is an object;

İşte bu fonksiyonun kodu, biraz çirkin olabilir ama bu fonksiyonun sadece ilk uygulamasıdır:

function createMapper<In, Out>(
    mapper: (input: In) => Out
): <Source extends In | In[]>(source: Source) => Source extends In[] ? Out[] : Out {
    return (source) => Array.isArray(source)
        ? source.map(mapper)
        : mapper(source);
}

Ve ts derleyicisi tarafından tür tanımında hiçbir hatam yok ama fonksiyon uygulamasında bir hatam var.

Type 'Out | Out[]' is not assignable to type 'Source extends In[] ? Out[] : Out'.
  Type 'Out' is not assignable to type 'Source extends In[] ? Out[] : Out'

Bu işlev oyun alanında mevcuttur:

https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABBATgUwIZTQWQwB3zRQB4BJMAGkQHkQoA+ACgChF3EBbAolALkRMYYfPQEUAlIgC8DWvRYSBJAMpwQKCGkRoAHtjAATAM6IKiAD5mwAbQC6zY+s1oBajVqmzE7lzv1oRqYU9ogA-PJQoQJ0UIgA3mwc6FAaSExOHmhecgCCKCgYAJ4AdDDG+YVFGc6eSRwcEZkuJdz4TG28EvUNiAKdxDVZEgDcLAC+SSxQRUSIePhkMgmIGABGEAIAjABMAMyI42MQCMZxbWQCC0vSK+ubiLsHRywsJ2BnXDxohpXFy6hMNgFrwSNdqNdmB0clwJEw-tU9hISsAYAAbNEdAhkCSjN6nOBotAlNFwADmWMIPwRJMCZKgAAtRogAPQsxBgOA6ApwFDGagnTj4dHERDgQzEM4YIKIRlYRAwOLlVZIDAFYpjfEfc7fQwANQwaJA2lugKwuG+pHB82xUM4MPtlJxxwJRJJ5MpRH1huNJXuzLZHK5xBQvP5yDgQpFKDFRklUGlJllDPlioVpmliDgawAVmhoCMgA

Bu hatanın neden olduğunu ve belki de düzeltilme yöntemini birisi açıklayabilir mi, lütfen.

Teşekkür ederim ve iyi günler!

Cevap #1

Sadece bu tür durumlarda fonksiyon aşırı yüklemesi:

function createMapper<In, Out>(
    mapper: (input: In) => Out
) {
    function condition<Source extends In | In[]>(source: Source): Source extends In[] ? Out[] : Out
    function condition(source: In | In[]) {
        return Array.isArray(source)
            ? source.map(mapper)
            : mapper(source);
    }

    return condition
}

type MapI = { abc: 123 };
const mapI: MapI = { abc: 123 };

const mappedArray = createMapper<MapI, MapI>((m) => m)(Array(3).fill(mapI)); // MapI[]


const mappedValue = createMapper<MapI, MapI>((m) => m)(mapI); // MapI

Oyun alanı

Dönüş türü yerine koşullu tipler TS tarafından desteklenmez