Допустим, вы хотите преобразовать типы number
в undefined
, заданный произвольным объектным литеральным типом, вот как мы это сделаем
type a = { e: string; f: number; l: boolean }
type b = { e: string; f: number; l: boolean }
type c = { e: string; f: number; l: { e: string; f: number; l: boolean } }
type ABC = { a: a; b: b; c: c }
type ConvertNumberToUndefined<T extends Record<string, unknown>> = {
[K in keyof T]: T[K] extends Record<string, unknown>
? ConvertNumberToUndefined<T[K]>
: T[K] extends number
? undefined
: T[K]
}
type newABC = ConvertNumberToUndefined<ABC>
type a_f = newABC['a']['f'] // undefined
// ^?
type b_f = newABC['b']['f'] // undefined
// ^?
type c_f = newABC['c']['l']['f'] // undefined
// ^?
playground
Теперь допустим, что мы хотим сохранить тип b
нетронутым, мы не хотим ничего менять, вот тогда нам пригодится интерфейс
type a = { e: string; f: number; l: boolean }
interface b { e: string; f: number; l: boolean }
type c = { e: string; f: number; l: { e: string; f: number; l: boolean } }
type ABC = { a: a; b: b; c: c }
type ConvertNumberToUndefined<T extends Record<string, unknown>> = {
[K in keyof T]: T[K] extends Record<string, unknown>
? ConvertNumberToUndefined<T[K]>
: T[K] extends number
? undefined
: T[K]
}
type newABC = ConvertNumberToUndefined<ABC>
type a_f = newABC['a']['f'] // undefined
// ^?
type b_f = newABC['b']['f'] // number
// ^?
type c_f = newABC['c']['l']['f'] // undefined
// ^?
игровое поле
просто преобразуйте b
в интерфейс, и все готово
это полезно, когда мы имеем дело с типом данных, который имеет особое значение, например, дата и геоточка