Зачем писать возвращаемый тип защиты типа как «это (…) и это» в TypeScript?

Я читаю раздел Классы в справочнике, но есть разница, которая меня смущает.

В следующих примерах:

  1. В примере 1 они сначала явно написали тип возвращаемого значения this is Networked & this. Я могу понять эту часть.

  2. Тогда в примере 2 они сделали только this is { value: T }, но тип box в блоке ifBox<string> & { value: string; }.

Я не знаю, почему работает второй случай. Основываясь на первом примере, я ожидаю, что вместо этого должно быть this is { value: T } & this. Означает ли это, что я всегда могу опустить явное & this?


Пример 1

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
}

Пример 2

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 this выглядит излишним.

user3840170 28.04.2024 09:08

Это определенно похоже на this is предикаты типа, реализованные в ms/TS#5906 на самом деле не волнует, является ли защищенный тип сужением входного типа, в отличие от предикатов обычного типа, которые выдадут вам ошибку TS2677, если вы попробуете это как показано здесь. Я предполагаю, что классы намеренно более свободны, чтобы подклассы случайно не сделали недействительным предикат типа. Но я не вижу нигде существующего документа/проблемы, где бы это точно говорилось. Если вам очень интересно, вы можете открыть для этого выпуск на GitHub.

jcalz 28.04.2024 16:22

(см. предыдущий комментарий). Если вы откроете вопрос и получите там официальный ответ, вы можете вернуться сюда и опубликовать его со ссылкой. В противном случае я просто не знаю, есть ли отличный способ получить объективный ответ на вопрос, почему это работает. Тот факт, что это работает, можно определить экспериментально или путем пошагового выполнения компилятора, но я не знаю, насколько это полезно для людей, особенно если нет документа, подтверждающего, что это работает.

jcalz 28.04.2024 16:24
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
3
3
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На всякий случай попробовал: да, можно опустить this. Защита типа всегда выполняется для экземпляра this, суженная версия всегда представляет собой какой-то вариант this, машинописный текст достаточно умен, чтобы это сделать.

Работает так же, как Extract

https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union

Другие вопросы по теме