Рассмотрим следующий код: (здесь также пример кода https://codesandbox.io/s/hbtew?file=/src/index.ts)
enum Types {TEXT, DATE}
interface TextState {
type: typeof Types.TEXT
}
interface DateState {
type: typeof Types.DATE
}
type State = TextState | DateState;
interface GenericProps {
state: State
}
interface InputProps<AnyState> {
state: AnyState;
}
function TextInput(props: InputProps<TextState>) {
}
function DateInput(props: InputProps<DateState>) {
}
const props: GenericProps = {state: {type: Types.TEXT}};
/*
Type 'State' is not assignable to type 'TextState'.
Type 'DateState' is not assignable to type 'TextState'.
Types of property 'type' are incompatible.
Type 'Types.DATE' is not assignable to type 'Types.TEXT'
*/
TextInput(props);
const {state} = props;
/*
Type 'State' is not assignable to type 'TextState'.
Type 'DateState' is not assignable to type 'TextState'
*/
TextInput({state: state});
/* OK */
TextInput({state: {type: Types.TEXT}});
/* OK */
DateInput({state: {type: Types.DATE}});
Как видите, при вызове TextInput(props) произошла ошибка. Не могли бы вы объяснить, как возникла эта ошибка и как исправить код, чтобы вызов TextInput(props) не выдавал ошибки? Цель состоит в том, чтобы иметь возможность сконструировать разные GenericProps, которые отличаются только type и могут быть переданы либо в TextInput(props) (если props = {state: {type: Types.TEXT}}), либо в DateInput(props) (если props = {state: {type: Types.DATE}}), спасибо!





Я бы предложил использовать ключевое слово as, оно обычно решает проблемы с типами. Ты можешь пойти как
varName: Type = anotherVarWithSlightlyDifferentType as Type
В вашем случае этого должно хватить
Обычно вам нужно «помочь» Typescript понять, что вы проверили тип реквизита, потому что в противном случае вы можете изменить тип состояния.
вы можете решить эту проблему, добавив функцию validateTextProps, которая выглядит так:
function validateTextProps(props: GenericProps): props is InputProps<TextState> {
return props.state.type === Types.TEXT;
}
const props: GenericProps = { state: { type: Types.TEXT } };
if (validateTextProps(props)){
TextInput(props);
}
Таким образом, Typescript понимает, что реквизиты имеют правильный тип, и позволяет вам вызывать TextInput (реквизиты).
Не совсем понимаю, что вы имеете в виду. Не могли бы вы указать конкретно?