Как расширить общий тип TypeScript?

Я хочу иметь тип/интерфейс, который включает в себя все свойства данного универсального типа и добавляет еще несколько, т.е. д., что расширяет его. Кроме того, я хочу иметь возможность «преобразовывать» любой объект этого типа в тот, который он расширяет.

Я никогда не буду создавать новый объект типа, который добавляет свойство, поскольку он будет действовать только как «контракт» для объекта. Таким образом, я предполагаю, что это никогда не должно быть классом.

До сих пор я пытался пересечь оба типа, например:

class MyClass{
   prop1: string;
   prop2: string;

   constructor(){
      this.prop1 = '1';
      this.prop2 = '2';
   }
}

type MyType<T> = T & {
   additionalProp: string;
}

myService.getData()
   .subscribe((res: MyType<MyClass>) => {
      //Do something with res.additionalProp...

      //This one should *not* have "additionalProp" yet it somehow does.
      let anObject: MyClass = <MyClass>res;

      console.info(anObject);
      //output: {prop1: '1', prop2: '2', additionalProp: 'valuefromresponse'}
   });

Может быть, это глупо с моей стороны, но я так и не понял, почему anObject в моем примере все еще имеет свойство MyType вводит.

Чтобы уточнить, я использую дженерики вместо прямого расширения MyClass, чтобы иметь возможность повторно использовать контракт MyType в коде.

Нет такой вещи, как литье в машинописном тексте. <MyClass> — это утверждение типа, и оно не влияет на объекты во время выполнения. Все типы стираются во время компиляции typescriptlang.org/docs/handbook/…

Aleksey L. 14.12.2020 12:15

Вы путаете тип времени выполнения с объявленным типом. Переменная anObject содержит тот же фактический объект, что и res, поэтому неудивительно, что журнал показывает это. Ваш слепок не имеет смысла - вы вводите в заблуждение машинопись о типе anObject.

Tomasz Gawel 14.12.2020 12:15
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой 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 для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
2
753
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Спасибо за помощь, @Aleksey L. и @Tomasz Gawel. Я оставил MyType то же самое и решил добавить следующее к MyClass:

static fromObject<T extends MyClass>(o: T) {
    return new MyClass(o.prop1, o.prop2);
}

Я знаю, что он использует статические методы и все такое, но это самое чистое решение, которое я мог придумать. Имея это, я могу вызвать let anObject: MyClass = MyClass.fromObject(res);, решив обе проблемы своим оригинальным подходом.

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