TS. Как правильно типизировать DTO в методе register(), чтобы пропала ошибка в блоке if-else?
Имеется следующий код:
class CustomerDTO {
public sameProp1!: string;
public sameProp2!: string;
public sameProp3!: string;
public role!: string;
public diffrentProp111!: string;
}
class TrainerDTO {
public sameProp1!: string;
public sameProp2!: string;
public sameProp3!: string;
public role!: string;
public diffrentProp222!: string;
}
class AuthSevice {
constructor() {}
async register(dto: CustomerDTO | TrainerDTO) {
const {sameProp1, sameProp2, sameProp3, role} = dto;
const user = {
sameProp1,
sameProp2,
sameProp3,
role,
registrationDate: new Date().toISOString(),
};
let customer;
let trainer;
if (role === 'customer') {
customer = {
...user,
diffrentProp111: dto?.diffrentProp111
}
} else {
trainer = {
...user,
diffrentProp222: dto?.diffrentProp222
}
}
}
}
Метод register может получать данные двух видов.
И в зависимости от того какие данные были получены мне нужно собрать, или объект customer, или объект trainer. Вот только сделать это не получается потому-то тайпскрипт ругается.
И я не могу понять что не так, почему опциональная цепочка(?.) не срабатывает в коде dto?.diffrentProp111 и dto?.diffrentProp222.
Ответы (1 шт):
В вашем случаи надо использовать Type Guards. Если у вас CustomerDTO и TrainerDTO являются классами, то можно сделать проверку if (dto instanceof CustomerDTO).
Также можно явно проверить наличие нужного вам свойства в объекте или использовать ключевые слова typeof или in. Для особо сложных ситуаций (или чтобы четко в коде указать что происходит проверка типов) можно написать функцию типа
function isFoo(arg: any): arg is Foo {...}
Вот рабочий пример для вашего кода:
class CustomerDTO {
public sameProp1!: string;
public sameProp2!: string;
public sameProp3!: string;
public role!: string;
public diffrentProp111!: string;
}
class TrainerDTO {
public sameProp1!: string;
public sameProp2!: string;
public sameProp3!: string;
public role!: string;
public diffrentProp222!: string;
}
class AuthSevice {
constructor() {}
async register(dto: CustomerDTO | TrainerDTO) {
const {sameProp1, sameProp2, sameProp3, role} = dto;
const user = {
sameProp1,
sameProp2,
sameProp3,
role,
registrationDate: new Date().toISOString(),
};
let customer;
let trainer;
if (dto instanceof CustomerDTO) {
customer = {
...user,
diffrentProp111: dto.diffrentProp111
}
} else {
trainer = {
...user,
diffrentProp222: dto.diffrentProp222
}
}
}
}