Я читаю раздел Классы в справочнике, но есть разница, которая меня смущает.
В следующих примерах:
В примере 1 они сначала явно написали тип возвращаемого значения this is Networked & this. Я могу понять эту часть.
Тогда в примере 2 они сделали только this is { value: T }, но тип box в блоке if — Box<string> & { value: string; }.
Я не знаю, почему работает второй случай. Основываясь на первом примере, я ожидаю, что вместо этого должно быть this is { value: T } & this. Означает ли это, что я всегда могу опустить явное & this?
class FileSystemObject {
isFile(): this is FileRep {
return this instanceof FileRep;
}
isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked(): this is Networked & this { // the return type here.
return this.networked;
}
constructor(public path: string, private networked: boolean) {}
}
class FileRep extends FileSystemObject {
constructor(path: string, public content: string) {
super(path, false);
}
}
class Directory extends FileSystemObject {
children: FileSystemObject[];
}
interface Networked { // this interface that matters.
host: string;
}
const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");
if (fso.isFile()) {
fso.content;
} else if (fso.isDirectory()) {
fso.children;
} else if (fso.isNetworked()) {
fso.host; // const fso: Networked & FileSystemObject
}
class Box<T> {
value?: T;
hasValue(): this is { value: T } { // here, there is no `& this`.
return this.value !== undefined;
}
}
const box = new Box<string>();
box.value = "Gameboy";
if (box.hasValue()) {
box.value; // notice the type of box here.
}
Это определенно похоже на this is предикаты типа, реализованные в ms/TS#5906 на самом деле не волнует, является ли защищенный тип сужением входного типа, в отличие от предикатов обычного типа, которые выдадут вам ошибку TS2677, если вы попробуете это как показано здесь. Я предполагаю, что классы намеренно более свободны, чтобы подклассы случайно не сделали недействительным предикат типа. Но я не вижу нигде существующего документа/проблемы, где бы это точно говорилось. Если вам очень интересно, вы можете открыть для этого выпуск на GitHub.
(см. предыдущий комментарий). Если вы откроете вопрос и получите там официальный ответ, вы можете вернуться сюда и опубликовать его со ссылкой. В противном случае я просто не знаю, есть ли отличный способ получить объективный ответ на вопрос, почему это работает. Тот факт, что это работает, можно определить экспериментально или путем пошагового выполнения компилятора, но я не знаю, насколько это полезно для людей, особенно если нет документа, подтверждающего, что это работает.






На всякий случай попробовал: да, можно опустить this. Защита типа всегда выполняется для экземпляра this, суженная версия всегда представляет собой какой-то вариант this, машинописный текст достаточно умен, чтобы это сделать.
Работает так же, как Extract
https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union
Я запутался в противоположном направлении. Написание
this is thisвыглядит излишним.