DEV Community

Acid Coder
Acid Coder

Posted on

Typescript When You Should Mix Type Alias And Interface

let say you want to convert number types to undefined given arbitrary object literal type, so here is how we do it

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
//   ^?
Enter fullscreen mode Exit fullscreen mode

playground

now let say we want to keep type b intact, we don't want to change anything, that is when interface come in handy

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
//   ^?
Enter fullscreen mode Exit fullscreen mode

playground

just convert b to interface and we are done

this is useful when we are dealing with data type that has special meaning, for example Date and Geopoint

Top comments (0)