Помните, что проверка типов в TypeScript static . Это происходит во время компиляции. Таким образом, вы не можете использовать TypeScript для проверки типов, которая зависит от условий выполнения.
Вы, конечно, можете объявить класс так, как вы это делаете, но для экземпляра будет вполне возможно иметь isAuthenticated
быть true
при friends
быть undefined
(или friends
быть массив, в то время как isAuthenticated
равен false
).
Для статической проверки типов вам необходимо использовать решение, исключенное в вопросе: отдельные типы для анонимных и аутентифицированных пользователей. Действие аутентификации AnonymousUser
вернет эквивалентный (но аутентифицированный) User
объект. (Акт отмены аутентификации аналогичным образом возвращает эквивалентный [но не прошедший проверку подлинности] AnonymousUser
объект.)
Учитывая, что вы этого не хотите, я бы сказал, что это должны быть свойства доступа, чтобы логика в классе могла гарантировать их согласованность. Например:
class User {
private _friends: User[] | undefined = undefined;
get isAuthenticated(): boolean {
return this.friends !== undefined;
}
get friends(): User[] | undefined {
return this._friends;
}
}
... и затем логика в классе делает пользователя аутентифицированным, задав this._friends to [];
(или отменяет аутентификацию, установив this._friends = undefined;
). Таким образом, экземпляр не может быть несовместимым, поскольку оба свойства зависят от одного и того же основного состояния.
(В этом примере используется закрытая версия TypeScript, но, конечно, вместо нее можно использовать закрытые поля JavaScript , если вы их используете.)
Если вы можете гарантировать, что экземпляры будут соответствовать типам, вы можете использовать для этого типы объединения. Предполагая, --strictNullChecks
:
declare type UnauthenticatedUser = {
isAuthenticated: false;
friends: undefined;
};
declare type AuthenticatedUser = {
isAuthenticated: true;
friends: User[];
}
declare type User = UnauthenticatedUser | AuthenticatedUser;
// Works
const u1: User = {
isAuthenticated: true,
friends: []
};
// Works
const u2: User = {
isAuthenticated: false,
friends: undefined
};
// Errors:
// > Type '{ isAuthenticated: true; friends: undefined; }' is not assignable to type 'User'.
// > Type '{ isAuthenticated: true; friends: undefined; }' is not assignable to type 'AuthenticatedUser'.
// > Types of property 'friends' are incompatible.
// > Type 'undefined' is not assignable to type 'User[]'."
const u3: User = {
isAuthenticated: true,
friends: undefined
};
на детской площадке
Затем примените правильный тип к любому пользователю.