Search code examples
typescripttypescript-generics

How to create a type from string and remove subtring?


I have an object with keys that end with some suffix and I want to get the keyof that object without the suffix.

e.g. where suffix = 'Svg'

type FooObj = {
    ASvg: any
    BSvg: any
    CSvg: any
    DSvg: any
}

type KeyofWithoutSuffix = WithoutSvgSuffix<keyof FooObj> 
// 'A' | 'B' | 'C' | 'D'

type WithoutSvgSuffix<T> = ???

How could I create the WithoutSvgSuffix type?

I think it needs some conditional type and string literal but I have no idea how that would be.


Solution

  • You can use conditional type inference and template literal types to strip a fixed suffix off a string literal:

    type WithoutSvgSuffix<T> = T extends `${infer P}Svg` ? P : never
    

    This results in the type you wanted:

    type KeyofWithoutSuffix = WithoutSvgSuffix<keyof FooObj>
    // 'A' | 'B' | 'C' | 'D'
    

    You haven't specified what you want to see happen if you pass in something that does not end in the suffix; the above definition just returns never for those, so they disappear entirely:

    type Test = WithoutSvgSuffix<"ESvg" | "FSVg" | "GgvS" | "HSvg">
    // typo ---------------------------> ~~~~~~   ~~~~~ <-- backwards
    // type Test = "E" | "H"
    

    If you want to see something else, you should replace never with whatever you want.

    Playground link to code