Home > other >  Typescript: generic conditional types error
Typescript: generic conditional types error

Time:08-01

I'm trying to learn more about conditional types in TS and, as a small challenge, decided to write something like a generic mapper. But I have stuck with an error

What I need to do:

  • into createMapper function need to pass a mapper;
  • from createMapper return a function which input property can receive a value or an array of values;
  • after passing a value ts compiler must explicitly understand what type is returned from a function;

something like:

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;

Here is a code of this function, it can be a little bit ugly, but it's only the first implementation of this function:

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);
}

And I have no errors in type recognition by ts compiler but I have an error in function implementation.


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'

This function is available in the playground:

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

Can anyone, please, explain why this error happening and maybe the method to fix it.

Thank you and have a nice day!

CodePudding user response:

Only function overloading in such cases:


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

Playground

COnsitional types in a place of return type does not supported by TS

  • Related