实现 pick 方法
从一个对象中,选择返回指定的属性值。
function pick<T, U extends keyof T>(data: T, keys: U[]): {[K in U]: T[K]} {
const temp: any = {};
for (let key of keys) {
temp[key] = data[key];
}
return temp;
}
上面代码中定义了两个范型T和U,T表示对象,U被限定为T的属性名(U extends keyof T),返回值的类型为{[K in U]: T[K]},in的作用就是遍历U这个数组。
可以看到数组元素被限制了只能是user对象里的key
可以推导出新对象的TypeScript类型。
实现useRequest
import { useEffect, useState } from 'react';
// 模拟请求接口,返回用户列表
function getUsers(): Promise<{ name: string }[]> {
return new Promise(resolve => {
setTimeout(() => {
resolve([
{
name: 'tom',
},
{
name: 'jack',
},
]);
}, 1000);
})
}
const App = () => {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState<Awaited<ReturnType<typeof getUsers>>>([]);
const [error, setError] = useState(false);
useEffect(() => {
setLoading(true);
getUsers().then((res) => {
setUsers(res);
}).catch(() => {
setError(true);
}).finally(() => {
setLoading(false);
})
}, []);
if (loading) {
return (
<div>loading...</div>
)
}
if (error) {
return (
<div>error</div>
)
}
return (
<div>
{users.map(u => (
<div key={u.name}>{u.name}</div>
))}
</div>
);
};
export default App;
这个例子实现了从后端请求用户列表并渲染。在加载数据时增加了loading效果。
const [users, setUsers] = useState<Awaited<ReturnType<typeof getUsers>>>([]);
- typeof getUsers 获取getUsers函数类型
- ReturnType 获取某个函数的返回值
Awaited如果函数返回值为Promise,这个可以获取到最终的值类型
如果每个请求都这么写比较麻烦,所以封装下 useRequest
function useRequest<T extends () => Promise<unknown>>(
fn: T,
): { loading: boolean; error: boolean; data: Awaited<ReturnType<T>> } {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [data, setData] = useState<any>();
useEffect(() => {
setLoading(true);
fn()
.then((res) => {
setData(res);
})
.catch(() => {
setError(true);
})
.finally(() => {
setLoading(false);
});
}, []);
return {
loading,
error,
data,
};
}
const {loading, error, data: users} = useRequest(getUsers);
推导出的data类型正确。 但是上边封装可能导致bug,如果请求失败,users为空,直播使用会报错。改造一下。
如果未请求成功,返回data为null。
为接口请求增加参数。
请求传参也能够正确推导出请求函数的参数类型。
总结
主要介绍了 U extends keyof T, {[K in U]: T[K]}, Awaited, ReturnType, Parameters 的使用,Awaited可以取到返回为Promise类型的函数的最终值类型。
参考: zustand源码学习