React中useState如何定义仅需部分API属性的类型?
React + TypeScript 处理 GitHub 用户数据的 useState 类型方案
1. 最优方案:仅定义你用到的属性类型
不需要创建包含API返回所有属性的Interface/Type,TypeScript支持类型收窄,只声明你实际使用的字段即可,既简洁又符合最小够用原则:
// 定义仅包含所需属性的类型 type GithubUser = { id: number; avatar_url: string; login: string; html_url: string; }; // 在useState中使用该类型 const [users, setUsers] = useState<GithubUser[]>([]);
这样既满足类型检查,又不会因为API返回字段变化(比如新增字段)而影响你的代码,因为你只关心自己用到的部分。
2. 关于泛型的使用
你尝试的<T[]>无效是因为没有明确指定T的具体类型。泛型需要配合具体类型约束才能生效,比如上面的例子其实就是用了泛型(useState<GithubUser[]>)——这里的GithubUser[]就是泛型参数的具体值。
如果想复用泛型逻辑(比如封装一个通用的获取数据Hook),可以这样写:
function useFetchData<T>(initialUrl: string) { const [data, setData] = useState<T[]>([]); useEffect(() => { fetch(initialUrl) .then(res => res.json()) .then((responseData: T[]) => setData(responseData)); }, [initialUrl]); return data; } // 使用时传入我们定义的GithubUser类型 const users = useFetchData<GithubUser>('https://api.github.com/users');
3. 不确定数据结构时的处理方式
如果暂时不确定返回数据的结构,不建议直接留空useState(那样会被推断为never[],后续赋值会报错),可以用以下两种方式:
- 用
unknown[]:最严格的方式,后续使用时需要先做类型断言或类型守卫const [users, setUsers] = useState<unknown[]>([]); // 使用时需要断言 const firstUserLogin = (users[0] as GithubUser).login; - 用
any[]:最宽松的方式,会跳过TypeScript的类型检查,不推荐长期使用,仅作为临时过渡方案const [users, setUsers] = useState<any[]>([]);
4. 要不要定义全量属性的类型?
除非你的业务逻辑需要用到API返回的所有字段,否则完全没必要。TypeScript的核心是类型安全,只要保证你用到的字段类型正确即可,多余的字段不会影响类型检查(API返回的额外属性会被TypeScript忽略,不会报错)。
内容的提问来源于stack exchange,提问作者Karan Badhwar
相关产品推荐
相关产品推荐

