9
头图

How to make all the attributes of a class selectable?

For example, I have the following type:

type User = {
  username: string;
  gender: 'male' | 'female';
  age: number;
  bio: string;
  password: string;
}

User type requires that all attributes must have values, so:

const user: User = {
  username: 'awesomeuser',
};

Is not feasible, it will prompt:

类型“{ username: string; }”缺少类型“User”中的以下属性: gender, age, bio

How to make it feasible? Use Partial to:

const user: Partial<User> = {
  username: 'awesomeuser'
}

Partial built-in inner type is to make all the attributes of a defined type optional. The specific implementation is as follows:

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

How to make all attributes of a type mandatory?

Suppose we have the following type definition:

type User = {
  username: string;
  age?: number;
  gender?: 'male' | 'female'
  bio?: string;
  password?: string;
}

Then got a series of user data results from the server backend:

const users: User[] = await api.users.list();

At this point, we try to access the user's age for comparison, and want to retrieve the user age > 18

const filteredUsers = users.filter(user => user.age > 18);

At this time, does your IDE prompt you: object may be "undefined". ? Why? Because we defined age itself as an optional attribute, when the attribute is not defined, its value is undefined , and in typescript , undefined is not allowed to number type, but at this time we can actually be sure api.users.list Interface returned to me, either throw an error or give to me it must be brought age value User type of data, so I can compare to, but because TypeScript do not know if the data you are loading User User with all attributes already have values, what should I do? What Required do.

const users: Required<User>[] = [];

Or let api.users.list() return type is Required<User>[] can be.

How to implement Required :

/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};

How to make all attributes of a type read-only?

Suppose we are writing a system now. When the user logs in, we will share a User object to all components, but only allow others to read its value and not allow others to modify it, but the User we defined is shared by the entire system and has editing functions. Pages are also using this type definition, they need to be able to modify user data, what should I do?

Use Readonly to:

const user = {
  username: "awesomeuser",
  gender: "male",
  age: 19,
  bio: "Aha, insight~",
};

const sharedUser = user as Readonly<User>;

sharedUser.username = "new Name";

At this point, the IDE will tell you that cannot be assigned to "username" because it is a read-only attribute.

Note that : TypeScript only performs static type checking, but it does not mean that these values cannot be modified. If you really want to create an object that cannot be modified programmatically, how can I solve it?

I want to have a class that only has some attribute definitions of another class

Still the User , I want to define a Login , which is specifically used for the type when logging in, but I don’t want to password username and 0613b10949d24e (although in this example, it is easy to rewrite it, but it is not the same. Someday will you encounter a very complicated type definition?), what should I do? Use Pick .

type User = {
  username: string;
  gender?: "male" | "female";
  age?: number;
  bio?: string;
  password?: string;
};

type Login = Pick<User, "username" | "password">;

const login: Login = {
  username: "pantao",
};

As you can see, the Login or only username is required, and password is optional. This does not meet our requirements. What should I do? Add Required .

type User = {
  username: string;
  gender?: "male" | "female";
  age?: number;
  bio?: string;
  password?: string;
};

type Login = Required<Pick<User, "username" | "password">>;

const login: Login = {
  username: "pantao",
};

You will be asked to enter password at this time.

How to implement Pick ?

/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

If you quickly define a type, attributes with the same data type?

Suppose we are currently developing a mall system, and each Store has a store manager, a warehouse manager, and a cashier. They are all associated with User . At this time, you can define the type Store

type User = {
  username: string;
  gender?: "male" | "female";
  age?: number;
  bio?: string;
  password?: string;
};

type Store = {
  name: string;
  location: string;
  leader: User;
  warehouseKeeper: User;
  cashier: User;
};

Of course, you can also define it like this:

type Store = Record<'leader' | 'warehouseKeeper' | 'cashier', User> & {
  name: string;
  location: string;
}

Which of the two methods is better, of course, has its own advantages and disadvantages, but suppose we encounter the following situation:

type User = {
  username: string;
  gender?: "male" | "female";
  age?: number;
  bio?: string;
  password?: string;
};

const users: User = [
  {
    username: "awesomeuser",
  },
  {
    username: "baduser",
  },
  {
    username: "gooduser",
  },
];

For the convenience of access, I want to convert the users variable into an object whose property name is users array index and value is users array element (ie User type). How to define such a type?

You can do this:

type UserSet = { [key: number]: User };

const userSet: UserSet = users.reduce(
  (set, user, index) => ({ ...set, [index]: user }),
  {} as UserSet
);

You can also do this:

type UserSet = Record<number, User>;

How to implement Record ?

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

大胡子民工潘半仙
4.8k 声望758 粉丝