zl程序教程

您现在的位置是:首页 >  前端

当前栏目

[Typescript] Handling conditional return type of a function

typescript of type Function return Handling Conditional
2023-09-14 08:59:11 时间
import { expect, it } from "vitest";
import { Equal, Expect } from "../helpers/type-utils";

function youSayGoodbyeISayHello(greeting: unknown) {
  return greeting === "goodbye" ? "hello" : "goodbye";
}

it("Should return goodbye when hello is passed in", () => {
  const result = youSayGoodbyeISayHello("hello");

  type test = [Expect<Equal<typeof result, "goodbye">>];

  expect(result).toEqual("goodbye");
});

it("Should return hello when goodbye is passed in", () => {
  const result = youSayGoodbyeISayHello("goodbye");

  type test = [Expect<Equal<typeof result, "hello">>];

  expect(result).toEqual("hello");
});

So in the function `youSayGoodbyISayHello`, we want both runtime and compile time type safety. The the return type of the function should either be `hello` or `goodbye` based on the input params is `goodbye` or `hello`.

 

Solution 1: using () as any

function youSayGoodbyeISayHello<T extends 'goodbye' | 'hello'>(
  greeting: T
): T extends 'goodbye' ? 'hello' : 'goodbye' {
  return (greeting === 'goodbye' ? 'hello' : 'goodbye') as any;
}

The idea is typescript is not smart enough to know greeting === 'goodbye' ? 'hello' : 'goodbyethe return type is string `goodbye` or `hello`, therefore you need to use as anyjust let typescript know, you know exactly what return type it is.

 

Solution 2: as GreetingReturnType<T>

type GreetingReturnType<T extends 'goodbye' | 'hello'> = T extends 'goodbye'
  ? 'hello'
  : 'goodbye';

function youSayGoodbyeISayHello<T extends 'goodbye' | 'hello'>(greeting: T) {
  return (
    greeting === 'goodbye' ? 'hello' : 'goodbye'
  ) as GreetingReturnType<T>;
}

 

----

The same as this one:

type Person = {
  name: string;
  age: number;
  birthdate: Date;
};

export function remapPerson<Key extends keyof Person>(
  key: Key,
  value: Person[Key]
): Person[Key] {
  if (key === 'birthdate') {
    return new Date() as Person[Key]; // return new Date() as any
  }

  return value;
}