Разница между расширением интерфейса и типом пересечения для реквизитов, расширяющих RouteComponentProps в компоненте класса Typescript React?

#javascript #reactjs #typescript #react-router

#javascript #reactjs #typescript #реагировать-маршрутизатор

Вопрос:

В чем разница между расширенным интерфейсом и типом пересечения в Typescript? Я не понимаю, чем отличается результирующий тип, особенно для простого случая расширения неперекрывающихся свойств.

В следующем примере ввода реквизита компонента класса реагирования, почему расширенный интерфейс не может правильно расширяться RouteComponentProps (который также является интерфейсом), но тип пересечения приводит к правильному вводу / свойствам?

 import React, {PureComponent} from 'react';
import {RouteComponentProps, withRouter} from 'react-router-dom';

// Interface fails to extend the properties
interface Props extends RouteComponentProps {}

// But if we used an intersection type, that works
// type Props = {} amp; RouteComponentProps

class MyComponent extends PureComponent<Props> {
    constructor(props: Props) {
        super(props);
    }

    render() {
        console.log('All props', this.props); // Prints all props including routing-related

        // Error here: Property 'history' does not exist on type 'Props'.  TS2339
        console.log('History - ', this.props.history);
        
        return <p>Hello World!</p>;
    }
}

export default withRouter(MyComponent);
  

IDE (VSCode), по-видимому, может получить правильный тип / свойства с помощью intellisense (используя оператор dot для отображения параметров автозаполнения). Однако компилятор Typescript выдает ошибку

 Property 'history' does not exist on type 'Props'.  TS2339
  

Я не понимаю, почему (поскольку я думал, что результирующий тип должен расширять те же свойства), но если Props определяется как тип пересечения с RouteComponentProps , то это работает.

 type Props = {} amp; RouteComponentProps;
  

Почему это так? Что происходит такого, что расширение интерфейса не удаляет свойства, как ожидалось?

В этом более простом игрушечном примере расширения интерфейса все работает как ожидалось, без ошибок компилятора TS.

 interface A {
    x: string;
}

interface B extends A {
    y: string;
}

function doSomething(something: B) {
    console.log(something.x);
}

doSomething({x: 'Whatever', y: 'Whatever'});
  

Итак, я запутался в том, как расширение интерфейса отличается от пересечения типов.

Чтобы повторить главный вопрос:
в чем разница между расширенным интерфейсом и типом пересечения в Typescript?

Попытка примера на игровой площадке TS

Пробуя пример кода в TS Playground на 3.9.7 (удобная ссылка с кодом и на 3.9.7), .d.ts определения импорта фактически подбираются, что довольно круто, но затем я получаю некоторые неочевидные ошибки консоли, а также ошибки боковой панели, которые на самом деле не отображаются. Смотрите Этот скриншот, который демонстрирует оба: Пример кода игровой площадки TS с ошибками консоли и боковой панели

Комментарии:

1. На самом деле нет разницы для этих целей, поскольку оба говорят, что Props обладают всеми свойствами RouteComponentProps . Когда я копирую и вставляю ваш код в Typescript playground, я не вижу ошибки, поэтому я не уверен, что здесь происходит не так.

2. @LindaPaiste Хорошая идея проверить на игровой площадке TS. Я нахожусь на TS 3.9.7. На игровой площадке для кода компонента класса он корректно выводит .d.ts определения для импорта, но не может выдавать JS, показывает значок для 73 ошибок на боковой панели, но фактические ошибки не отображаются, и консоль имеет несколько экземпляров этой ошибки : index.js:24 Uncaught (in promise) Error: Debug Failure. False expression: Paths must either both be absolute or both be relative . Можете ли вы подтвердить, что вы использовали верхний блок кода (компонент класса) и что вы не видели никаких ошибок боковой панели или консоли? ТЬФУ!

3. Также обратите внимание, что для меня сам код не выделяется красными закорючками или чем-то еще. Я не получаю никаких отзывов от игровой площадки, кроме количества значков ошибок и ошибок консоли, для которых они не предназначены. Для удобства bit.ly сокращенный URL-адрес находится по адресу /34i3PYB (Извините, его пришлось сократить, потому что код, закодированный в URL, сделал его слишком длинным для публикации полного URL. Кроме того, SO не позволил бы мне опубликовать небольшую ссылку целиком. Ссылка на игровую площадку моего примера кода с TS 3.9.7). Надеюсь, другие смогут воспроизвести то, что я вижу.