TS – a Pick

Topic link

Implement the built-in Pick

for TS, but do not use it.
,>

Select attribute K from type T to construct a new type.

Such as:

interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoPreview = MyPick<Todo, 'title' | 'completed'>

const todo: TodoPreview = {
    title: 'Clean room'.completed: false,}Copy the code

I. Key word description

Type: indicates type protection

The function of type is to give a type a new name (alias). It supports primitive types, union types, progenitors, and any other handwritten type you need. It is often used for union types, like interfaces, to describe the type of an object or function

Typeof is the typeof js, ts will automatically infer the type from the typeof your code:

 // This is how type is usually defined
  type PersonType = {
    name: string
    age: number
  }

  let people = {
    name: 'people'.age: 20,}// Typeof can be defined by an ordinary object as type A and then used to constrain other variables
  type PersonType1 = typeof people 
  let p1: PersonType = {
    name: 'man'.age: 12,}Copy the code

pick

Pick in TS source code implementation:

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
Copy the code

What it does is extract all the K from T and generate a new type. The User type defined in the following example contains two mandatory attributes including puberty and age. So, if you specify people as User, you must include both attributes, or you will get a type-checking error:

interface User {
  stature: number
  age: number
}

const people: User = {
  stature: 186.age: 20,}Copy the code

However, if I want people to contain only User type of stature attributes, I can do this with Pick. It tells TS to only extract the stature attributes from User.

// Success, the new types generated with Pick do contain only typical attributes
const people: Pick<User, 'stature'> = {
  stature: 185,}// error, the new type generated with Pick does not contain the age attribute
const people: Pick<User, 'stature'> = {
  age: 17,}Copy the code

PS :Pick is to extract a single attribute from all attributes of the type.

interface

Interface official link

It is equivalent to the JS object in the type, used to check the structure type of functions, classes, etc. The so-called structure type check, that is, the structure of two types is the same, then their types are compatible, which is also known as “duck type” in the world of computer science.

Cue what duck type? When a bird is seen walking like a duck, swimming like a duck, and quacking like a duck, it can be called a duck.

Now we want the todo object to make a type annotation. We can define an Interface to annotate it in the manner of the “duck type” mentioned earlier:

interface Todo {
  content: string;
  user: string;
  time: string;
  isCompleted: boolean;
}

const todo: Todo = {
 // ...
}
Copy the code

The type generated interface

interface IPerson { name: string age: number like: Array < string >} interface IPickedPerson extends Pick < IPerson, 'name' | 'like' > {} / const p/generate a new interface: IPickedPerson = { name: 'zs', like: ['a', 'b'] }Copy the code

2. Use of pick

Scenario: Take a combination of several desired types from a composite type.

// Primitive type
interface TState {
	name: string;
	age: number;
	like: string[];
}
// If you want only name and age, you can define one more
interface TSingleState {
	name: string;
	age: number;
}
// The disadvantage is that when Tstate changes, TSingleState does not change with it, so Pick should be used instead
interface TSingleState extends Pick<TState, "name" | "age"> {};
Copy the code

Generally we use extends for inheritance, but what about writing in generics? Generics constrain official documents

In the previous example, we sometimes wanted to manipulate a set of values of a certain type, and we knew what properties that set of values had. In the demo example, we tried to access the length property of value, but the compiler could not prove that every type has the length property, so we reported an error.

function demo<T> (value: T) :T {
    console.log(value.length);  // Error: T doesn't have .length
    return value;
}
Copy the code

Instead of operating on all types of any, we want to restrict the function to any type with a.length attribute. As long as the type passed in has this attribute, we allow, that is, at least include this attribute. To do this, we need to list the constraints on T.

To do this, we define an interface to describe the constraints. Create an interface that contains the.length attribute and use this interface and the extends keyword to implement the constraint:

interface Lengthwise {
    length: number;
}

function demo<T extends Lengthwise> (value: T) :T {
    console.log(value.length);  // Now we know it has a .length property, so no more error
    return value;
}

// Now the generic function is constrained, so it no longer applies to any type:
demo(3);  // Error, number doesn't have a .length property
// We need to pass in a value that matches the constraint type, which must contain the required attributes:
demo({length: 10.value: 3});
Copy the code

Third, antithesis

interface Todo {
  title: string
  description: string
  completed: boolean
}
// Retrieve a series of K attributes from T
type MyPick<T, K extends keyof T> = { [S in K]: T[S] }

type TodoPreview = MyPick<Todo, 'title' | 'completed'>

const todo: TodoPreview = {
    title: 'Clean room'.completed: false,}Copy the code

Extends is used in generics not to inherit, but to constrain types. So the K extends keyof T, which means that the key is bound to the keyof T.