Хорошо - так что мне удалось заставить это работать. Текущее решение удовлетворяет двум основным требованиям для меня:
Выводит defaultProps
для дочернего компонента, который упаковывается, если они присутствуют, то есть компонент, сгенерированный оболочкой HoC, не нуждается в явно передать их.
Предоставить объединение свойств оболочек HoC и свойств нижестоящих компонентов, чтобы Intellisense отображал все доступные свойства для упакованного компонента.
В моем стремлении упростить то, что происходит на самом деле, типы, ожидаемые функцией withHoC
, жестко закодированы (в моем случае react-select
), поэтому оболочка withHoC
будет принимать только react-select
. ] Select
компонент для переноса. Все остальное, вероятно, приведет к ошибкам типа.
В этой ссылке описан некоторый код, который может автоматически выводить тип компонента, который должен быть упакован с помощью withHoC
, делая withHoC
многократно используемым с типами компонентов, отличными от react-select's
Select
,
// node dependencies used (because dependencies mutate so much this may not work in other versions):
// "react": "^16.8.2",
// "react-dom": "^16.8.2",
// "typescript": "^3.3.3",
// "react-select": "2.4.1",
// "@types/react": "^16.8.3",
// "@types/react-dom": "^16.8.2",
// "@types/react-select": "^2.0.13",
// Visual Studio 2017 TypeScript SDK build 3.3.3
import ReactDOM from "react-dom"; // (Optional - just for testing)
import React from "react";
import Select from "react-select";
// Properties shape for React Select (See react-select @type definitions)
import { Props } from "react-select/lib/Select";
// The properties we are want to add so that our resultant wrapped component contains all of its own properties plus the extra properties specified here
interface IHOCProps {
bar: string;
}
function withHoC(WrappedComponent: React.ComponentType) {
return class SomeHOC extends React.Component {
// If 'bar' isn't specified, configure a default (this section is optional)
static defaultProps = {
bar: "default bar"
};
public render(): JSX.Element {
return <>{this.props.bar} >;
}
};
}
const WrappedSelect = withHoC(Select);
export { WrappedSelect, Select };
// Test it out (Optional). If using Visual Studio 2017 or some other IDE with intellisense,
// should show all the 'react-select' properties and the HoC property (bar).
// Additionally, all the defaultProps for 'react-select' are automatically inferred so no TypeScript errors about missing props when using .
const TestMe = () =>
<>
>;
// Append the result to an HTML document body element
ReactDOM.render( ,document.getElementsByTagName("body")[0]);
В некоторой степени пиррова победа, поскольку она не может быть повторно использована разными типами, но она работает.
Один последний самородок; если вы используете Visual Studio 2017 и узел для TypeScript, убедитесь, что версия TypeScript SDK синхронизирована с пакетом узла npm, в противном случае среда IDE может сообщать об ошибках, которые не проявляются при компиляции командной строки (это не дало мне конца проблем красной сельди).
Microsoft опубликовала этот URL , который редко обновляется и, вероятно, устарел, но никто в корпорации не заметил.
Последний SDK всегда можно найти на GitHub здесь , который обычно всегда публикуется вместе с пакетами npm и nuget. [1 125]
Едва ли. Здесь существует четыре условия, таким образом, я пробегусь через каждого из них:
интерфейс является абстрактным классом (на языках как Java, где нет никакого множественного наследования, иногда существуют другие ограничения, такие как отдельный тип данных), который предназначается, чтобы использоваться в качестве общей базы для доступа ко многим так же ведущим себя объектам. Концептуально, нет никакого требования для абстрактности, но обычно, интерфейс будет иметь по крайней мере один абстрактный метод. Интерфейс является методом для Вашей программы для общения со многими подобными классами, каждым с различной семантикой, но той же общей целью.
контракт является неявным соглашением, которое Вы заключаете между пользователями и реализаторами класса или интерфейса. Например, предварительные условия и постусловия (инварианты обычно являются контрактом в рамках реализации класса - обычно, вещи как отношение между внутренними участниками, не должны быть выставлены). Спецификация для возвращаемого значения или аргумента может также быть частью контракта. Это в основном представляет, как использовать функцию/класс/интерфейс и не является обычно полностью представимым ни на каком языке (некоторые языки, как Eiffel, позвольте Вам вставлять явные контракты, но даже они не могут всегда полностью излагать в деталях требования). Когда Вы реализуете интерфейс или происходите из класса, необходимо всегда отвечать интерфейсным требованиям, или, при переопределении неабстрактного класса, для поведения достаточно подобные, что внешнее средство просмотра не замечает различия (это - принцип замены Лисков; производный объект должен быть способен к замене основы без различия в поведении с внешней точки зрения).
классу не нужен большой осмотр, так как Вы ясно использовали их прежде. Класс является типом данных, и на некоторых языках надмножество интерфейсов (которые не имеют никакого формального определения, как в C++), и в других независимо (такой как в Java).
объект является экземпляром типа класса (или любого нетипа класса, обычно). Точное определение объекта очень характерно для языка, но общим определением является фактическая вещь, упомянутая несколькими ссылками/указателями на то же самое - например, на некоторых языках как Java, == выдерживает сравнение, являются ли две переменные тем же объектом, не обязательно, являются ли они семантически тем же. Объекты независимы от классов или интерфейсов - они представляют единственный экземпляр. Другой способ думать о нем состоит в том, что класс или интерфейс являются формой, и объект является физическим объектом, который выходит из формы (довольно плохая аналогия, но лучше, чтобы я мог придумать прямо сейчас).
Нет, не действительно. Класс является шаблоном, который Вы определяете. Каждый объект, который инстанцирует того класса, следует за шаблоном. Они не действительно избыточные условия, потому что эти две вещи не идентичны. Можно думать о классе как о пользовательском типе данных. Классы и объекты отличаются друг от друга тем же самым способом, которым примитивный тип данных int
отличается от литерального значения 3.
, интерфейс определяет ряд методов, которые должны поддерживать все классы с реализацией. Сам интерфейс является контрактом, который Вы определяете для классов с реализацией. Это просто говорит, что любой класс, который реализует интерфейс, должен иметь набор того интерфейса открытых методов.
Хорошо я предполагаю..., если интерфейс указывает контракт, чем класс указывает (или несколько) экземпляр (экземпляры) конкретного объекта.
Терминология менее важна, чем приложение все же.
На самом деле интерфейс является контрактом, когда объект является экземпляром класса - они - разные вещи, у которых не есть слишком много общее.
интерфейс просто обеспечивает фасад для объектов или гарантию для вызывающей стороны, что объект может сделать некоторую операцию, даже не зная, что это - реализация.
, Например, Вы можете иметь два класса, реализовывая тот же интерфейс/контракт, но сделать полностью разные вещи (даже при том, что значение выполнения их может быть тем же).
Берут интерфейс IDisposable, например: Каждый объект может высвободить средства, которые он использует, но он может сделать это по-разному, он может принять решение не выпустить что-либо. Это - выбор объекта.
, По крайней мере, это было бы POV в.NET
Завершать предыдущие ответы, слово об интерфейсах:
, Если класс является больше, чем шаблон для объекта (из-за его глобальных характеристик, независимых от каких-либо экземпляров), интерфейс может быть также быть описанным как точка зрения
класс А, реализовав несколько интерфейсов:
"Точка зрения" означает, что Вы можете с помощью объекта путем фокусировки только на контракте, определяют тем интерфейсом.
Это находится в том аспекте, интерфейс является "абстрактным классом", как в "абстракции" (что-то, что берет после некоторых характеристик класса, но пропустите некоторых других). В мире Java интерфейс уезжает на самом деле много, так как он может только быть применен для определения контракта, например, не для статических методов или функций.
"Класс" и "Объект" представляют две разных вещи; они связаны, но что они представляют, отличается, вполне сильно.
лучший способ описать это состоит в том, чтобы посмотреть на Статический. Класс может иметь статических участников, которые являются абсолютно отдельными от любого ЭКЗЕМПЛЯРА того класса. Объекты того класса могут или не могут использовать тех статических участников; но экземпляр объекта того класса является абсолютно отдельным от любого статического использования того класса (или должен быть, по крайней мере).
Или думают о шаблоне "одиночка". Хранение экземпляра объекта класса в статическом средстве доступа класса является обычной практикой и показывает различие. Вы посылаете к класс статическое средство доступа добраться экземпляр объекта из singleton-класса; если класс статический участник не имеет экземпляр объекта для обращения к, , класс создает экземпляр из объект .
Другими словами; объект экземпляр класса; но класс может быть [еще 1112] , чем просто шаблон, из которого инстанцируют объекты. У статических членов классов есть представление в памяти, которая абсолютно независима от экземпляров объектов тех классов.