Typescript выводит значение из подмножества объединения для условного типа

#typescript #type-inference

#машинописный текст #вывод типа

Вопрос:

Я ищу небольшую помощь в выводе типов, чтобы сузить объединение в TypeScript на основе условного типа.

Наш API принимает набор параметров и проверяет их. Как часть процесса проверки, он нормализует все значения, чтобы упростить последующую обработку. Одним из параметров может быть либо массив строк, либо массив массива строк. При нормализации это значение всегда преобразуется в массив массива строк.

Чтобы избежать необходимости явно выписывать каждый проверенный тип (и поддерживать их) Я пытаюсь вывести проверенные параметры из входящих параметров (которые имеют одинаковые ключи) с разрешенным значением. Например:

 type IncomingParams = {
   names: string[] | Array<string[]> | undefined
   ages: string[] | undefined
}

// Post validation the object is the following
type Validated = {
   names: Array<string[]>
   ages: string[]

}
 

Это то, что я придумал, но это не гарантирует, что при наличии объединения оно всегда преобразуется в массив массива.

 type ArrayUnion<T> = T[] | T[][];

type Params = {
   names: ArrayUnion<string>
   ages: string[]
}

type ValidatedParams<P> = {
    [K in keyof P]: P[K] extends ArrayUnion<infer U>
        ? U[][]
        : NonNullable<P[K]>;
};

const validated: ValidatedParams<Params> = {} as any;

validated.names // This should be string[][]
validated.ages // This should be string[]
 

Возможно, Typescript не может различить объединение, поэтому один из вариантов, который я исследовал, — использовать amp; { readonly _sym: unique symbol } для однозначной идентификации ArrayUnion , хотя этот подход тоже не сработал.

Я был бы признателен за любую помощь заранее.

Игровая площадка TypeScript

Комментарии:

1. Используя ваш код, если я присваиваю validated.names переменной (например, const test = validated.names ), кажется, что она имеет ожидаемый string[][] тип.

2. Привет @AlbertoRivera, спасибо. Я собрал игровую площадку. как ни странно, я получаю ошибку, которую я записал локально, но, используя игровую площадку, я получаю string[[] — однако ages свойство также является string[][], когда оно должно быть string[]

3. @J-R основываясь на информации, которую вы предоставили в комментарии выше, это наводит меня на мысль, что в вашем рабочем пространстве / проекте используется более старая версия Typescript, в которой он не мог правильно определить тип. попробуйте обновить project / workspace до более новой версии TS, чтобы узнать, устраняет ли это проблему. Кроме того, может быть полезно включить ваш файл tsconfig.json при публикации вопросов TS, поскольку иногда это может привести к непредвиденным проблемам с конфигурацией, которые не отображаются в playground.

4. ages это string[][] потому, что оно расширяется ArrayUnion , поскольку это массив. Кроме того, в вашем случае использования, если names предварительная проверка была string[] , должна ли она быть string[][] после проверки?

5. Привет @r3wt спасибо за предложение, я воссоздал его в ссылке playground выше, в которой содержится конфигурация. Я обновил свою локальную версию typescript, и теперь она отражает проблему на игровой площадке.

Ответ №1:

Похоже, что undefined добавление вызвало некоторые проблемы. Вот решение, работающее на игровой площадке TS

https://www.typescriptlang.org/play?experimentalDecorators=falseamp;emitDecoratorMetadata=falseamp;target=2amp;module=1#code/PTAEHUHsCcGsEsB2BzUBnSAbArgF3pIgFBG4CeADgKagCC00AhmQKqIGIA8AKgHygBeUAG1uoAD6huwgLoAaUADplACmkyJU2bICUGydkQATKgDMkVIyXLVQABUZMAtmkGgA3kVDfEjJ1TQALjoGZjYOTjRcaCRkXi9vRmQA4KiYlFk5BNBIXAALKmhg iZWdkJI6Nj4gF9rShoANUZMeCNGXEsHZzROO34hT29vYQBpUCRQWCoySFN7GWC7MY0qAA9O41cSsPKuJFNC0BZ44bPQAH5QADlCa xMTEYAI0wqThPtGWzz4NvEe6PF5vPorXgAbiINUhRAAxoQoqAAG4tNodSzBZqtdqdIzdPy9fEuAYeGqgRiuRiIMgwlHY9FGRS fyuUAgKR5eCuNB5SAPIygZ40NKxL5EOlo3GKJIBbzs7ic7m8-mC4VVDLfIjsgDChFh0CoHQmTgomH8iFwHQ4cIRuFAFEcBKWjpcbiGwxlQREACIsEZvfIfsyUj6AFZ AIBrJnXIFIqgQwmcyISxQkjwxCIh09ABMzp6bp nuCwl9mH9gbOwa9wlL4ZZUbDkDyiG9Cm97SRVADleGscKJbrEbQjbrzdb7c73fkPopFcDdSAA