typescript 可选的通用属性

标签 typescript generics type-inference typescript-generics

我有这种类型,我的 value属性是“可选的”(如果 T 不是 undefined )

type AsyncState<T = undefined> = {
    value?: T;
    loading: boolean;
    error: { reason: string } | null;
}

现在我需要以某种方式创建依赖于 AsyncState 的新对象参数 - 添加 value属性如果 T不是 undefined如果 T未定义。 (这只是更复杂逻辑的虚拟示例,但由于类型是问题,所以应该足够了)
function asyncGet<T>(initialState: AsyncState<T>) {
    return typeof initialState.value !== 'undefined' 
        ? (s: AsyncState<T>) => ({ ...initialState })
        : (s: AsyncState) => ({ loading: initialState.loading, error: initialState.error });
}


const first: AsyncState<string> = {
    loading: true,
    error: null,
    value: ""
}

const second: AsyncState<string> = {
    loading: true,
    error: null,
    value: ""
}

const creator = asyncGet(first);

/* 
Argument of type 'AsyncState<string>' is not assignable to parameter of type 'AsyncState<string> & AsyncState<undefined>'.
  Type 'AsyncState<string>' is not assignable to type 'AsyncState<undefined>'.
    Type 'string' is not assignable to type 'undefined'.
*/
creator(second);

这是typescript playground .

最佳答案

您可以通过创建需要推断 T 的实际类型的返回函数来解决此问题。通用的。

function asyncGet<T>(initialState: AsyncState<T>) {
  return typeof initialState.value !== "undefined"
    ? (s: AsyncState<T>) => ({ ...initialState })
    : <U>(s: AsyncState<U>) => ({
        loading: initialState.loading,
        error: initialState.error
      });
}

也就是说,如果你试图通过这样调用来覆盖 TypeScript 的推理,这会给你带来麻烦:asyncGet<string>({ loading: true, error: null })
更好的解决方案是使用条件类型来指定函数有条件地使用对返回函数的调用的推断值。
function asyncGet<T>(initialState: AsyncState<T>): 
  <U>(s: AsyncState<[T] extends [undefined] ? U : T>) => 
    AsyncState<[T] extends [undefined] ? U : T> {

  return typeof initialState.value !== "undefined"
    ? (s) => ({ ...initialState })
    : (s) => ({
        loading: initialState.loading,
        error: initialState.error
      });
}

关于 typescript 可选的通用属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57860176/

相关文章:

f# - 试图理解推断的类型约束

TypeScript 条件通用接口(interface)作为参数(数组或对象,基于 bool 值)

typescript - 在使用 jest 测试数据对应于 TypeScript 类型时避免警告

java泛型加法

generics - 没有类型参数的泛型类型的泛型结构

generics - 可克隆类型和可复制类型的特征

Java 泛型类型推断奇怪的行为?

reactjs - 这是扩展 Material-UI 组件的正确方法(React/Typescript)

typescript - 如何将分离的 Koa-Router 与 Typescript 结合起来

typescript - 推断回调参数的类型