У меня есть тип и интерфейс, который его расширяет:
type IntrinisicDivProps = JSX.IntrinsicElements['div'];
interface SomeComponentProps extends IntrinisicDivProps {
// added properties
}
Это прекрасно работает. Однако мне кажется, что мне не нужно делать тип IntrinisicDivProps. В конце концов, я, по сути, говорю: «A = B, расширяется от B», так не должен ли я иметь возможность сказать «продолжается от A непосредственно»?
Я ожидал, что это сработает:
interface SomeComponentProps extends JSX.IntrinsicElements['div'] {
// added properties
}
... но это не так. Я получил:
An interface can only extend an identifier/qualified-name with optional type arguments.ts(2499)
Как у моего IntrinisicDivProps есть «аргументы необязательного типа», а у JSX.IntrinsicElements['div'] нет, хотя один буквально = другой:
type IntrinisicDivProps = JSX.IntrinsicElements['div'];
Разве это не одно и то же?
Думайте об этом как об ограничении синтаксиса, а не семантического ограничения. Есть открытый вопрос... ой, посмотрите, @jonrsharpe только что связал его. Хорошо, он может написать ответ...
Если я правильно понимаю, это проблема «ТС тупой»? TS видит выражение и выдает ошибку, поскольку знает, что выражения могут содержать нерасширяемые элементы (например, идентификатор или полное имя)... хотя мое конкретное выражение этого не делает. Помещение его в переменную типа каким-то образом сообщает TS, что «это выражение не имеет идентификаторов или квалифицированных имен»?
Конечно, говоря «тупой», я просто имел в виду, что инструмент не способен понять содержимое выражения… Я не пытаюсь оскорбить TypeScript :)
Конечно, ТС неспособен этого «понять»; это синтаксическое ограничение. Вы можете расширять именованные типы, включая универсальные именованные типы, а не выражения произвольных типов. Некоторые именованные типы по-прежнему не являются расширяемыми (например, type A = {a: string} | {b: number}; interface C extends A {} не удастся). Это нереализованная функция. Проблема, указанная выше, является каноническим ответом на этот вопрос. Достаточно ли этого, если кто-то это напишет? Или мы еще что-то упускаем в этом вопросе?
Кажется, я понял: до того, как я поместил его в type, выражение было просто выражением, но после того, как я поместил его в type, это именованный тип. Синтаксически TS написан просто для того, чтобы позволить вам расширять именованные типы, а не расширения (вероятно, потому, что было бы что-то запутанное в разрешении выражений?). Другими словами, в TS после того, как вы сделаете type x = y, x !== y (потому что в этот момент x — это тип, а y — выражение). Если я прав, более или менее, мне просто нужен ответ, чтобы принять :)






Это недостающая функция TypeScript, запрошенная по адресу microsoft/TypeScript#31843 . В настоящее время существует синтаксическое ограничение на то, какие типы типов могут быть расширены интерфейсом. Это означает, что даже если два типа семантически идентичны, они могут обрабатываться по-разному, если они написаны с разным синтаксисом. Синтаксически вы можете расширить только «идентификатор/полное имя с необязательными аргументами типа», что в основном означает, что он должен быть именованным типом (где «аргументы необязательного типа» означают, что это может быть именованный общий тип как ну.) Это синтаксическое ограничение ни для чего не требуется, поэтому указанный выше запрос на функцию открыт, а не отклонен. Но так обстоит дело в настоящее время.
Но это означает, что вы всегда можете обойти это ограничение, используя простой псевдоним общего типа
type Named<T> = T;
И это работает, потому что теперь синтаксически запрещенный тип становится аргументом типа, который разрешен:
interface SomeComponentProps extends Named<JSX.IntrinsicElements['div']> {
}
Обратите внимание, что это не позволяет вам обойти семантическое ограничение только на расширение типов объектов или пересечений типов объектов со статически известными членами (как это реализовано в microsoft/TypeScript#13604):
interface Oops extends Named<{ a: 0 } | { b: 1 }> { } // error, union
interface Whoops<T> extends Named<T> { }// error, unknown properties
interface Nope<T> extends Named<
T extends string ? { a: 0 } : { b: 1 }
> { } // error, generic conditional
IntrinisicDivPropsимеет «аргументы необязательного типа»» — это не так, но идентификатор или квалифицированное имя могут.