Я переношу проект React с TypeScript для использования функций перехватчиков (React v16.7.0-alpha), но я не могу понять, как установить типизацию деструктурированных элементов.
Вот пример:
interface IUser {
name: string;
}
...
const [user, setUser] = useState({name: 'Jon'});
Я хочу, чтобы user
переменная была типа IUser
. Мое единственное успешное испытание состоит из двух этапов: ввод, затем инициализация:
let user: IUser;
let setUser: any;
[user, setUser] = useState({name: 'Jon'});
Но я уверен, что есть способ получше. Кроме того, она setUser
должна быть инициализирована как функция, которая принимает в IUser
качестве входных данных и ничего не возвращает.
Также стоит отметить, что использование const [user, setUser] = useState({name: 'Jon'});
без какой-либо инициализации работает нормально, но я хотел бы воспользоваться преимуществом TypeScript для принудительной проверки типов при инициализации, особенно если это зависит от некоторых свойств.
Спасибо за вашу помощь.
источник
IUser
, т.е. имеет те же свойства. Это называется утиным набором текста.type MyType = MyObj[];
тогдаuseState<MyType>
useState
возвращает хорошо типизированный кортеж, который назначен,[user, setUser]
и для TypeScript нетрудно понять, что переменные должны быть того же типа, что и составляющие кортежа. Не знаю, прояснил ли я ситуацию или запутал вас еще больше.Сначала
useState
берется общий, которым будет ваш IUser. Если после этого вы захотите передать второй деструктурированный элемент, возвращаемый им,useState
вам потребуется импортировать Dispatch. Рассмотрим эту расширенную версию вашего примера с обработчиком кликов:import React, { useState, Dispatch } from 'react'; interface IUser { name: string; } export const yourComponent = (setUser: Dispatch<IUser>) => { const [user, setUser] = useState<IUser>({name: 'Jon'}); const clickHander = (stateSetter: Dispatch<IUser>) => { stateSetter({name : 'Jane'}); } return ( <div> <button onClick={() => { clickHander(setUser) }}>Change Name</button> </div> ) }
Смотрите этот ответ .
источник
Вы также можете объявить начальное состояние раньше, а затем иметь возможность вызывать его в любое время:
type User = typeof initUser; const initUser = {name: 'Jon'} ... const [user, setUser] = useState<User>(initUser);
О префиксах интерфейса I: https://basarat.gitbooks.io/typescript/content/docs/styleguide/styleguide.html#interface
источник
https://fettblog.eu/typescript-react/hooks/
// import useState next to FunctionComponent import React, { FunctionComponent, useState } from 'react'; // our components props accept a number for the initial value const Counter:FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => { // since we pass a number here, clicks is going to be a number. // setClicks is a function that accepts either a number or a function returning // a number const [clicks, setClicks] = useState(initial); return <> <p>Clicks: {clicks}</p> <button onClick={() => setClicks(clicks+1)}>+</button> <button onClick={() => setClicks(clicks-1)}>-</button> </> }
источник