Улучшенный Partial

Можно ли сделать тип с такой сигнатурой:

type Optional<T> = ...

…который мог бы преобразовать это:

type A = {
    a: number
    b: string[]
}

…в это:

type Optional_A = {
    a?: number | null
    b?: (string | null | undefined)[] | null
}

С преобразованием св-ва a нет никаких проблем:

type BadOptional<T> = { [K in T]?: K | null }

Основная проблема с массивом. Если бы TypeScript поддерживал нечто подобное:

type ImpossibleOptional<T> = {
    [K in T]?: (K extends U[]
        ? (U | null | undefined)[]
        : K) | null
}

…то решение нашлось бы само собой, но нет.


Ответы (1 шт):

Автор решения: Qwertiy

Playground

type A = {
  a: number
  b: string[]
}

type MyOptEx<T> = {
  [key in keyof T]?: T[key] extends (infer U)[] ? (U | null | undefined)[] | null : T[key] | null;
}

type OptA = MyOptEx<A>

Получается:

type OptA = {
    a?: number | null | undefined;
    b?: (string | null | undefined)[] | null | undefined;
}

Хотя вообще-то, возможно стоит прописывать явно и undefined для значения - вдруг когда-то typescript передумает и перестанет его сам добавлять. Хотя, вероятно, это уж слишком breaking change для них, но постепенно туда движутся. Может быть очередным strict-флагом добавят.

Оказывается, такой флаг уже есть: exactOptionalPropertyTypes.

→ Ссылка