根据第二个可选参数键入typescript函数中的第一个参数

wfypjpf4  于 2023-03-09  发布在  TypeScript
关注(0)|答案(1)|浏览(128)

我正在为React开发一个状态管理器库,我想添加一个帮助函数,允许用户使用选择器从React外部轻松设置深度嵌套的状态,到目前为止,帮助函数看起来如下所示:

type NestedStateSetter<State> = <Selected = State>(
    update: Selected | (() => Selected) | (() => Promise<Selected>),
    selector?: (state: State) => Selected
) => Promise<Selected>;

const initialState = {
    a: {
        b: {
            c: 0,
        },
    },
};

const setState: NestedStateSetter<typeof initialState> = (update, selector) => {
    throw "Yeet"
};

setState(1, (state) => state.a.b.c) // Ok
setState(() => 2, (state) => state.a.b.c) // Ok
setState(async () => 5, (state) => state.a.b.c) // Not ok

但第三次调用'setState'时,在上面第三次调用的(state) => state.a.b.c上出现了此错误:
类型'(状态:{ a:{ B:{ c:编号; }; };})=〉编号'无法赋值给类型'的参数(状态:{ a:{ B:{ c:编号; }; };})=〉Promise '。类型'number'不能赋给类型' Promise '。(2345)
TypeScriptPlayground链接
Stackblitz link
我尝试使用curried函数,但那将是一个突破性的变化,我宁愿尽可能避免它。

pobjuy32

pobjuy321#

您需要从最特定到最不特定对联合中的类型进行排序,以防止TypeScript匹配第一个最泛型的类型。
因此,代替:

update: Selected | (() => Selected) | (() => Promise<Selected>)

use:

update: (() => Promise<Selected>) | (() => Selected) | Selected
    • 完整片段:**
type NestedStateSetter<State> = <Selected = State>(
  update: (() => Promise<Selected>) | (() => Selected) | Selected,
  selector?: (state: State) => Selected
) => Promise<Selected>;

const initialState = {
  a: {
    b: {
      c: 0,
    },
  },
};

const setState: NestedStateSetter<typeof initialState> = (update, selector) => {
  throw 'Yeet';
};

setState(1, (state) => state.a.b.c); // Ok
setState(
  () => 2,
  (state) => state.a.b.c
); // Ok
setState(
  async () => 5,
  (state) => state.a.b.c
); // Ok

Playground链接

相关问题