Скажем, у меня есть класс с универсальным параметром. У него есть условные типы для некоторых свойств класса. Эти условные типы зависят от универсального параметра, являющегося одним из двух возможных значений перечисления. В конструкторе я передаю тип, который следует тем же границам типа, что и универсальный параметр. Я ожидаю, что проверка login_type === TwoChoices.REGISTER
сузит тип универсального параметра класса T
, однако этого не происходит. Вот пример.
enum TwoChoices {
LOGIN,
REGISTER
}
class ConditionalGenericClass<T extends TwoChoices> {
password: string;
email: string;
username?: T extends TwoChoices.REGISTER ? string : never;
constructor(login_type: T) {
this.password = '';
this.email = '';
if (login_type === TwoChoices.REGISTER) {
this.username = '';
}
}
}
Вышеупомянутый бросает TypeError
: Type '""' is not assignable to type '(T extends TwoChoices.REGISTER ? string : never) | undefined'.
.
Я ожидал, что смогу написать, это просто добавить защиту типа с C extends TwoChoices.REGISTER
в качестве возвращаемого типа функции, например:
enum TwoChoices {
LOGIN,
REGISTER
}
function typeGuardExtendsTwoChoicesRegister<C extends TwoChoices>
(login_type: C): C extends TwoChoices.REGISTER
{
return login_type === TwoChoices.REGISTER;
}
class ConditionalGenericClass<T extends TwoChoices> {
password: string;
email: string;
username?: T extends TwoChoices.REGISTER ? string : never;
constructor(login_type: T) {
this.password = '';
this.email = '';
if (typeGuardExtendsTwoChoicesRegister(login_type)) {
this.username = '';
}
}
}
Однако похоже, что X extends Y
не является допустимым возвращаемым типом защиты типа.
Каков правильный, лучший способ статического ввода таких сценариев динамического типа в JavaScript?
Вероятно, вы предложите использовать наследование классов следующим образом:
class LoginCredentials {
password: string;
email: string;
constructor() {
this.password = '';
this.email = '';
}
}
class RegisterCredentials extends LoginCredentials {
username: string;
constructor() {
super();
this.username = '';
}
}
Но, на мой взгляд, необходимость изменить способ кодирования только для кодирования типов, похоже, не соответствует моему пониманию философии TypeScript, заключающейся в том, что это просто надмножество JavaScript, в которое вы просто добавляете некоторую информацию для ввода, но вместо этого требуется, чтобы вы изменили способ вы кодируете JavaScript. Использование классов также удваивает количество строк при переносе до ≤es5
, особенно при использовании const enum
s в первом блоке кода по сравнению с методом наследования классов.