React Typescript 泛型类型重载(例如 useState)
Posted
技术标签:
【中文标题】React Typescript 泛型类型重载(例如 useState)【英文标题】:React Typescript Generic Type Overloading (e.g. useState) 【发布时间】:2021-05-21 16:04:48 【问题描述】:我正在尝试创建一个重载函数,该函数将写入和写入会话存储而不是标准状态。我希望它在我只提供类型而不是初始值的情况下是可重载的。就像 useState
在 react 中所做的一样。
这是我目前所拥有的:
export function useSessionState<S = undefined>(initialState?: S): [S, (state: S) => void];
export function useSessionState<S>(initialState: S): [S, (state: S) => void]
const [state, setState] = useState<S>()
// Unimportant: Do something to load to and from session storage.
return [state, (value) =>
]
当我尝试使用这种类型时,我只会得到其中一个重载的结果类型。
// Variable 'state' is a string as expected.
const [state, setState] = useSessionState("some_initial_value")
// Variable 'undefinedState' is also a string, but it should be undefined since no 'initialState' was provided.
const [undefinedState, setUndefinedState] = useSessionState<string>()
【问题讨论】:
【参考方案1】:我自己也不知道答案,所以我开始阅读和尝试。我的尝试非常接近,但我发现了以下缺陷:
两次尝试都将initialState
显示为S
类型,而不是S | undefined
,这意味着您很难在没有强制转换的情况下实现此功能。
第一种方案和第二种方案生成的.d.ts
不同。我相信第一次尝试的.d.ts
更接近官方的useState
定义。
即使您没有提及:
initialState
可以是一个值,也可以是一个函数,这只是第二次尝试的情况。
setState
函数应该有一个S | undefined
类型的参数,而不是S
。
希望有更好的解决方案... 如果只有 actual implementation 是用 Typescript 编写的。
尝试 1:Conditional types
Playground
function useState<S>(initialState: S): [S, (state: S) => void];
function useState<S = undefined>(): [S | undefined, (state: S) => void];
function useState<S = undefined>(initialState?: S): [S extends undefined ? undefined | S : S, (state: S) => void]
throw new Error(`Not implemented and not using $initialState`);
const [state1, setState1] = useState<string>("initialValue"); // string
const [state2, setState2] = useState("initialValue"); // string
const [state3, setState3] = useState<string>(); // undefined | string
const [state4, setState4] = useState(); // undefined
在操场上生成的.d.ts
:
declare function useState<S>(initialState: S): [S, (state: S) => void];
declare function useState<S = undefined>(): [S | undefined, (state: S) => void];
尝试 2:没有条件类型
Playground
type Dispatch<T> = (value: T) => void;
function useState<S = undefined>(): [S | undefined, Dispatch<S | undefined>];
function useState<S>(initialState?: S | (() => S)): [S, Dispatch<S>];
function useState<S>(initialState?: S | (() => S)): [S, Dispatch<S>]
throw new Error(`Not implemented and not using $initialState`);
const [state1, setState1] = useState<string>("initialValue"); // string
const [state2, setState2] = useState("initialValue"); // string
const [state3, setState3] = useState<string>(); // undefined | string
const [state4, setState4] = useState(); // undefined
在操场上生成的.d.ts
:
declare function useState<S = undefined>(): [S | undefined, Dispatch<S | undefined>];
declare function useState<S>(initialState?: S | (() => S)): [S, Dispatch<S>];
【讨论】:
编辑添加第二次尝试。以上是关于React Typescript 泛型类型重载(例如 useState)的主要内容,如果未能解决你的问题,请参考以下文章
Typescript核心篇——函数_this指向—重载—泛型