TS Advanced Usage summary “two”

The main content of this article: Typeof, conditional type

The article takes about 6 minutes to read.

Typeof type operator

Note that type is a type alias

// Prints "string"
console.log(typeof "Hello world");
Copy the code

Using Typeof automatically returns the type, which is not very useful for primitive types, but in combination with other type operators, you can easily use Typeof to represent many schemas.

function f() {
  return { x: 10.y: 3 };
}
type P = ReturnType<typeof f>;
// type P = {
// x: number;
// y: number;
// }
Copy the code

Or you can do it by index

type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
// type Age = number
Copy the code

Another example of using an arbitrary type for indexing is using T to get the type of an array element. We can combine it with typeof to easily capture the element typeof an array literal:

const MyArray = [
  { name: "Alice".age: 15 },
  { name: "Bob".age: 23 },
  { name: "Eve".age: 38},];type Person = typeof MyArray[T];    
// type Person = {
// name: string;
// age: number;
// }

type Age = typeof MyArray[T]["age"]; 
// type Age = number

// Or
type Age2 = Person["age"];
// type Age2 = number
Copy the code

Conditions in the

At the heart of most useful programs, we must make decisions based on input. The program is no different, but given that values can be easily introspected, these decisions are also based on the type of input. Condition types help describe the relationship between input and output types.

interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}

type Example1 = Dog extends Animal ? number : string;
// Dog is derived from Animal
// type Example1 = number
 
type Example2 = RegExp extends Animal ? number : string;
// type Example2 = string
Copy the code

If we have an overloaded function, see how we can override it using this condition type. The overload of createLabel describes a JavaScript function that selects based on the input type

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
 
function createLabel(id: number) :IdLabel;
function createLabel(name: string) :NameLabel;
function createLabel(nameOrId: string | number) :IdLabel | NameLabel;
function createLabel(nameOrId: string | number) :IdLabel | NameLabel {
  throw "unimplemented";
}
Copy the code

rewrite

type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;

// We can use this condition type to simplify overloading into a single function without overloading
function createLabel<T extends number | string> (idOrName: T) :NameOrId<T> {
  throw "unimplemented";
}
let a = createLabel("typescript");
// let a: NameLabel
let b = createLabel(2.8);
// let b: IdLabel
let c = createLabel(Math.random() ? "hello" : 42);
// let c: NameLabel | IdLabel
Copy the code

conclusion

The conditional type part, there are some more advanced use, but I think, can first understand the content of this article, and then to learn more advanced. You may not use it in your daily life, but when you read the source code, you’ll see the benefits of type constraints!

Read the Vue3 source code, if you don’t know the advanced uses of TS, you may be confused; However, if you are reading the source code for the first time, it is recommended to find an “easy” version within the community.

👍 👍 👍

Start with Mini-Vue: gitHub repository that implements the simplest Vue model!