Home > Net >  Typescript function returns partial only if parameter is partial
Typescript function returns partial only if parameter is partial

Time:11-17

I have a function that for a given camelCase object returns the same object in snake_case

// Let's imagine these are the types
interface CamelData {
   exempleId: number
   myData:string
}

interface SnakeData {
   exemple_id: number
   my_data: string
}

export const camelToSnake = (
  camelData: Partial<CamelData>
): Partial<SnakeData> => {
  return {
    exemple_id: camelData.exempleId,
    my_data: camelData.myData
}

The thing is I want my function returning type to be SnakeData whenever camelData is of type CamelData.

Basically something that works like that

export const camelToSnake = (
  camelData: Partial<CamelData>
): if (camelData is of type CamelData) {SnakeData} else {Partial<SnakeData>} => {
  return {
    exemple_id: camelData.exempleId,
    my_data: camelData.myData
}

Can you help ? Have a great day

CodePudding user response:

Function overloading:

export function camelToSnake (camelData: CamelData): SnakeData;
export function camelToSnake (camelData: Partial<CamelData>): Partial<SnakeData>;
export function camelToSnake (camelData: Partial<CamelData>): Partial<SnakeData> {
  return {
    exemple_id: camelData.exempleId,
    my_data: camelData.myData
  }
}

CodePudding user response:

You can use a generic type for the input and if it it extends CamelData then the return type is SnakeData, otherwise just use partials:

// Let's imagine these are the types
interface CamelData {
   exempleId: number
   myData:string
}

interface SnakeData {
   exemple_id: number
   my_data: string
}
// exported call signature is specified seperately so inside the function it just needs to typecheck to a partial
// you can just use one call signature but convincing typescript the data fits the type `T extends CamelData ? SnakeData : Partial<SnakeData>` without typecasts is hard.
export function camelToSnake<T extends Partial<CamelData>>(
  camelData: T
): T extends CamelData ? SnakeData : Partial<SnakeData>
export function camelToSnake(
  camelData: Partial<CamelData>
): Partial<SnakeData>{
  return {
    exemple_id: camelData.exempleId,
    my_data: camelData.myData
    }
}

const x = camelToSnake({exempleId:1})
//   ^? const x: Partial<SnakeData>
const y = camelToSnake({exempleId:2, myData: "hi"})
//   ^? const y: SnakeData

playground link

Here I used a single overload so that typescript doesn't try to typecheck inside the function for the conditional type since that'd be hard, to do it with arrow notation it'd be the only option though:

const camelToSnake = <T extends Partial<CamelData>>(
    camelData: T
):T extends CamelData ? SnakeData : Partial<SnakeData> => ({
    exemple_id: camelData.exempleId,
    my_data: camelData.myData
} as T extends CamelData ? SnakeData : Partial<SnakeData>)
  • Related