Typescript — автоматическое наследование реквизитов типа в обратном вызове реакции

#reactjs #typescript

Вопрос:

Имея такую реализацию

 // CustomComponent.ts
type SaveProps = {
    date: string;
    name: string;
}

interface IProps {
    onSave: (props: SaveProps) => void;
}

const CustomComponent = ({onSave}: IProps) => {
    return (
        <button onClick={() => onSave({ date: '', name: '' })}>
            Click me
        </button>
    );
};


// ParentComponent.ts
import CustomComponent from './CustomComponent';

export default function ParentComponent () {
    
    const saveData = props => { // what type is props? how to infer this as SaveProps defined in CustomComponent.ts?
        
    }

    return (
        <CustomComponent onSave={saveData} />
    )
}
 

Как я могу определить тип реквизита в сохраненных данных как реквизит, не импортируя его тип? Чтобы при чтении реквизитов в обратном вызове SaveData я автоматически знал, какие данные отправляет пользовательский компонент.

Ответ №1:

В большинстве случаев лучше экспортировать Props тип вместе с компонентом. В вашем конкретном случае вы можете сделать следующее:

 import { IProps, CustomComponent } from './CustomComponent';

function ParentComponent () {
    const saveData = React.useCallback((props => {
    }) as IProps['onSave'], []);

    return (
        <CustomComponent onSave={saveData} />
    )
}
 

Игровая площадка TS

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

1. да, импорт действительно заключает сделку, но разве нет другого элегантного решения? 🙂

2. Я буду придерживаться этого

Ответ №2:

Извините за еще один ответ. Комментарии ограничены максимальной длиной.

https://www.typescriptlang.org/docs/handbook/type-inference.html#contextual-typing

TS достаточно умен, чтобы выводить типы в разных направлениях, и им управляет множество эвристических алгоритмов. Вот почему мы не можем реорганизовать ваш пример в соответствии с каким-либо общим набором правил (такого нет).

Еще один трюк без явного экспорта Props :

 (props => {
}) as Parameters<typeof CustomComponent>[0]['onSave']
 

Игровая площадка TS

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

1. хм, да, это тоже путь, но гораздо более громоздкий, чем «импортный»…