再也无需前思后想,一切岂非已然过往。——《且听风吟》
题目:
/*
Intro:
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.
*/
interface User {
type: 'user';
name: string;
age: number;
occupation: string;
}
interface Admin {
type: 'admin';
name: string;
age: number;
role: string;
}
type PowerUser = unknown;
export type Person = User | Admin | PowerUser;
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' },
{
type: 'powerUser',
name: 'Nikki Stone',
age: 45,
role: 'Moderator',
occupation: 'Cat groomer'
}
];
function isAdmin(person: Person): person is Admin {
return person.type === 'admin';
}
function isUser(person: Person): person is User {
return person.type === 'user';
}
function isPowerUser(person: Person): person is PowerUser {
return person.type === 'powerUser';
}
export function logPerson(person: Person) {
let additionalInformation: string = '';
if (isAdmin(person)) {
additionalInformation = person.role;
}
if (isUser(person)) {
additionalInformation = person.occupation;
}
if (isPowerUser(person)) {
additionalInformation = `${person.role}, ${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);
console.log();
console.log('Power users:');
persons.filter(isPowerUser).forEach(logPerson);
// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/utility-types.html
// https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types
报错:
index.ts(53,12): error TS2571: Object is of type 'unknown'.
index.ts(57,12): error TS2571: Object is of type 'unknown'.
index.ts(61,12): error TS2571: Object is of type 'unknown'.
index.ts(73,36): error TS2571: Object is of type 'unknown'.
index.ts(73,52): error TS2571: Object is of type 'unknown'.
index.ts(75,20): error TS2571: Object is of type 'unknown'.
index.ts(75,36): error TS2571: Object is of type 'unknown'.
test.ts(5,5): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(16,5): error TS2344: Type 'false' does not satisfy the constraint 'true'.
test.ts(27,5): error TS2344: Type 'false' does not satisfy the constraint 'true'.
答案:
/*
Intro:
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.
*/
interface User {
type: 'user';
name: string;
age: number;
occupation: string;
}
interface Admin {
type: 'admin';
name: string;
age: number;
role: string;
}
type PowerUser = Omit<User,'type'>&Omit<Admin,'type'>&{ type: 'powerUser' };
export type Person = User | Admin | PowerUser;
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' },
{
type: 'powerUser',
name: 'Nikki Stone',
age: 45,
role: 'Moderator',
occupation: 'Cat groomer'
}
];
function isAdmin(person: Person): person is Admin {
return person.type === 'admin';
}
function isUser(person: Person): person is User {
return person.type === 'user';
}
function isPowerUser(person: Person): person is PowerUser {
return person.type === 'powerUser';
}
export function logPerson(person: Person) {
let additionalInformation: string = '';
if (isAdmin(person)) {
additionalInformation = person.role;
}
if (isUser(person)) {
additionalInformation = person.occupation;
}
if (isPowerUser(person)) {
additionalInformation = `${person.role}, ${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);
console.log();
console.log('Power users:');
persons.filter(isPowerUser).forEach(logPerson);
// In case you are stuck:
// https://www.typescriptlang.org/docs/handbook/utility-types.html
// https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types