We are starting a small community of users. For performance reasons we have decided to store all users right in the code. This way we can provide our developers with more user-interaction opportunities. With user-related data, at least. All the GDPR-related issues we will solved some other day. This would be the base for our future experiments during these exercises.
Exercise:
Given the data, define the interface "User" and use it accordingly.
不难发现 persons 数组既有 User 又有 Admin。 因此 person 的函数签名应该是两者的联合类型。而题目又让我们补充 Person,于是代码将 Person 定义为 Admin 和 User 的联合类型就不难想到。
代码
核心代码:
1
exporttype Person = User | Admin;
这个时候, persons 数组使用的过程只能用 User 和 Admin 的共有属性, 也就是 name 和 age,这点后面的题目也会提到。 因此如果你使用了 role 或者 occupation 就会报错。怎么解决呢? 我们继续看下一题。
第三题
题目描述
1 2 3 4 5 6 7 8 9 10 11 12 13
Intro:
Since we already have some of the additional information about our users, it's a good idea to output it in a nice way.
Exercise:
Fix type errors in logPerson function.
logPerson function should accept both User and Admin and should output relevant information according to the input: occupation for User and role for Admin.
另外一种方式是使用类型收缩,比如 is , in, typeof , instanceof 等。使得 Typescript 能够 Get 到当前的类型。”哦, person 上有 role 属性啊,那它就是 Admin 类型,有问题我 Typescript 的锅“
这里我们使用 in 操作符,写起来也很简单。
推荐哪种不用我多说了吧 ?
代码
1 2 3 4 5 6 7
if ("role"in person) { // person 会被自动推导为 Admin additionalInformation = person.role; } else { // Person 会被自动推导为 User additionalInformation = person.occupation; }
第四题
题目描述
1 2 3 4 5 6 7 8 9 10 11 12
Intro:
As we introduced "type" to both User and Admin it's now easier to distinguish between them. Once object type checking logic was extracted into separate functions isUser and isAdmin - logPerson function got new type errors.
Exercise:
Figure out how to help TypeScript understand types in this situation and apply necessary fixes.
这样当 isAdmin 返回 true, 那么 person 变量就会被推导成 Admin 类型,而不是联合类型, 也就是类型发生了收缩。
不难看出,这样的类型断言会直接影响到调用 isAdmin 或 isUser 的函数的入参的类型。
第五题
题目描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Intro:
Time to filter the data! In order to be flexible we filter users using a number of criteria and return only those matching all of the criteria. We don't need Admins yet, we only filter Users.
Exercise:
Without duplicating type structures, modify filterUsers function definition so that we can pass only those criteria which are needed, and not the whole User information as it is required now according to typing.
exportconst isAdmin = (person: Person): person is Admin => person.type === "admin"; exportconst isUser = (person: Person): person is User => person.type === "user";
exportfunctionlogPerson(person: Person) { let additionalInformation = ""; if (isAdmin(person)) { additionalInformation = person.role; } if (isUser(person)) { additionalInformation = person.occupation; } console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`); }
Filtering requirements have grown. We need to be able to filter any kind of Persons.
Exercise:
Fix typing for the filterPersons so that it can filter users and return User[] when personType='user' and return Admin[] when personType='admin'. Also filterPersons should accept partial User/Admin type according to the personType. `criteria` argument should behave according to the `personType` argument value. `type` field is not allowed in the `criteria` field.
Higher difficulty bonus exercise:
Implement a function `getObjectKeys()` which returns more convenient result for any argument given, so that you don't need to cast it.
let criteriaKeys = Object.keys(criteria) as (keyof User)[]; --> let criteriaKeys = getObjectKeys(criteria);
Filtering was completely removed from the project. It turned out that this feature was just not needed for the end-user and we spent a lot of time just because our office manager told us to do so. Next time we should instead listen to the product management.
Anyway we have a new plan. CEO's friend Nick told us that if we randomly swap user names from time to time in the community, it would be very funny and the project would definitely succeed!
Exercise:
Implement swap which receives 2 persons and returns them in the reverse order. The function itself is already there, actually. We just need to provide it with proper types. Also this function shouldn't necessarily be limited to just Person types, lets type it so that it works with any two types specified.
Project grew and we ended up in a situation with some users starting to have more influence. Therefore, we decided to create a new person type called PowerUser which is supposed to combine everything User and Admin have.
Exercise:
Define type PowerUser which should have all fields from both User and Admin (except for type), and also have type 'powerUser' without duplicating all the fields in the code.
题目大概意思是定义一个类型 PowerUser, 里面包含 User 和 Admin 的所有属性, 并且有一个字段是固定的 type: ‘powerUser’。