This is the sixth day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

String literal type

The string literal type allows you to specify a fixed value that a string must have.

type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
  animate(dx: number, dy: number, easing: Easing) {
    if (easing === "ease-in") {}else if (easing === "ease-out") {}else if (easing === "ease-in-out") {}}}let button = new UIElement();
button.animate(0.0."ease-in");
// button.animate(0, 0, "uneasy"); // error: Argument of type '"uneasy"' is not assignable to parameter of type 'Easing'.
Copy the code

Numeric literal type

function rollDie() : 1 | 2 | 3 | 4 5 | | 6{
  // ...
}
Copy the code

Enumerator type

An enumerator is typed when each enumerator is initialized with a literal.

enum ShapeKind {
  Circle,
  Square,
}
interface Circle {
  kind: ShapeKind.Circle;
  radius: number;
}
interface Square {
  kind: ShapeKind.Square;
  sideLength: number;
}
let c: Circle = {
  kind: ShapeKind.Square,
  // Error! Type 'ShapeKind.Square' is not assignable to type 'ShapeKind.Circle'.
  radius: 100,}Copy the code

Discriminated Unions

First we declare the interfaces to be federated. Each interface has a kind attribute but has a different string literal type. A kind attribute is called an identifiable feature or tag.

// Declare the interface to be federated
interface Square {
  kind: "square";
  size: number;
}
interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}
interface Circle {
  kind: "circle";
  radius: number;
}
type Shape = Square | Rectangle | Circle; // Type alias
function area(s: Shape) {
  switch (s.kind) { // Type protection on the kind attribute
    case "square": return s.size * s.size;
    case "rectangle": return s.height * s.width;
    case "circle": return Math.PI * s.radius ** 2; }}Copy the code

Index types

A common JavaScript pattern is to select a subset of properties from an object.

function pluck(o, names) {
  return names.map(n= > o[n]);
}
Copy the code

In TypeScript, this is written as follows:

function pluck<T.K extends keyof T> (o: T, names: K[]) :T[K] []{
  return names.map(n= > o[n]);
}
interface Person {
  name: string;
  age: number;
}
let person: Person = {
  name: 'Jarid'.age: 35
};
let strings: string[] = pluck(person, ['name']); // ok, string[]
Copy the code

The compiler checks to see if name is really an attribute of Person.

First, for any type T, the result of keyof T is the union of known public property names on T. Such as:

let personProps: keyof Person; // 'name' | 'age'
Copy the code

Second, T[K] is the index access operator, and person[‘name’] has the type person[‘name’].

Index type and string index signature

  • If you have a string with the type of index sign, so keyof T be string | number.

  • T[string] is the type of the index signature:

interface Fn<T> {
  [key: string]: T;
}
let keys: keyof Fn<number>; // string | number
let value: Fn<number> ['foo']; // number
Copy the code

Mapping type

TypeScript provides a way to create new types from old types – mapping types. In a mapping type, the new type converts every attribute of the old type in the same way. For example, you can make each attribute of type Readonly or optional.

Mapping types are the utility types described earlier, such as Partial

and Readonly

.

reference

  • Advanced Types · TypeScript Chinese Language