取悦于人并不困难,问题只是你是否能够了解别人的喜恶心理。——卡耐基

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*

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.

*/

interface User {
type: 'user';
name: string;
age: number;
occupation: string;
}

interface Admin {
type: 'admin';
name: string;
age: number;
role: string;
}

export type Person = User | Admin;

export const persons: Person[] = [
{ type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
{ type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
{ type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
{ type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' }
];

export function isAdmin(person: Person) {
return person.type === 'admin';
}

export function isUser(person: Person) {
return person.type === 'user';
}

export function logPerson(person: Person) {
let additionalInformation: string = '';
if (isAdmin(person)) {
additionalInformation = person.role;
}
if (isUser(person)) {
additionalInformation = person.occupation;
}
console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}

console.log('Admins:');
persons.filter(isAdmin).forEach(logPerson);

console.log();

console.log('Users:');
persons.filter(isUser).forEach(logPerson);

// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

报错:

1
2
3
4
index.ts(52,40): error TS2339: Property 'role' does not exist on type 'Person'.
Property 'role' does not exist on type 'User'.
index.ts(55,40): error TS2339: Property 'occupation' does not exist on type 'Person'.
Property 'occupation' does not exist on type 'Admin'.

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*

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.

*/

interface User {
type: 'user';
name: string;
age: number;
occupation: string;
}

interface Admin {
type: 'admin';
name: string;
age: number;
role: string;
}

export type Person = User | Admin;

export const persons: Person[] = [
{ type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
{ type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
{ type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
{ type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' }
];

export function isAdmin(person: Person): person is Admin {
return person.type === 'admin';
}

export function isUser(person: Person): person is User {
return person.type === 'user';
}

export function logPerson(person: Person) {
let additionalInformation: string = '';
if (isAdmin(person)) {
additionalInformation = person.role;
}
if (isUser(person)) {
additionalInformation = person.occupation;
}
console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}

console.log('Admins:');
persons.filter(isAdmin).forEach(logPerson);

console.log();

console.log('Users:');
persons.filter(isUser).forEach(logPerson);

// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

这里的方法返回值可以指定为person is User,非常酷炫