TypeScript——一些高级类型推断的问题;尝试为 Rematch 构建更好的类型

标签 typescript generics

我目前正在研究高级 TypeScript 类型——我的任务是(在中期)改进 types for rematch .

所以,到目前为止我所做的是:

interface ModelDefinition<TState> {
    state: TState;
    reducers: TReducers<TState>;
}
interface TReducers<TState> {
    [reducerName: string]: TReducer<TState>;
}
type TReducer<TState> = (state: TState, payload: any) => TState;

function createModel<TModelDefinition extends ModelDefinition<TModelDefinition["state"]>>(modelDefinition: TModelDefinition): void {
     // ...
}

// Now, this can be used as follows:
createModel({
    state: 42,
    reducers: {
        setValueTo21: (oldState: number, payload: any) => 21
    }
});

此时系统会自动检查state是否匹配每个reducer的第一个参数;并且 reducer 返回正确的状态类型。

注意:我故意不使用简单的 TState 泛型参数,因为当类型不匹配时,错误不会显示在不匹配的 reducer 处,而是显示在状态处定义。

对于上述类型,我无法添加一个新属性 effects,它是一个方法。如果我使用 lambda 语法,它会起作用。

作品:

createModel({
    state: 42,
    reducers: {
        setValueTo21: (oldState: number, payload: any) => 21
    },
    effects: () => {}
});

休息时间:

createModel({
    state: 42,
    reducers: {
        setValueTo21: (oldState: number, payload: any) => 21
    },
    effects() {}
});

错误消息显示在 setValueTo21 中:

Type '(oldState: number, payload: any) => number' is not assignable to type 'TReducer<unknown>'.
  Types of parameters 'oldState' and 'state' are incompatible.
    Type 'unknown' is not assignable to type 'number'. [2322]

再次工作:

有趣的是,当我在函数体外部提取函数定义时,没有发生类型推断错误:

const effects = function() {
}
createModel({
    state: 42,
    reducers: {
        setValueTo21: (oldState: number, payload: any) => 21
    },
    effects
});

总结

这对我来说真的很奇怪。顺便说一句——我正在运行最新的 TypeScript 版本。任何人都有任何提示,也许我遇到了什么错误? (对我来说,即使在 TypeScript 错误跟踪器中也很难找到可能存在此问题的错误)。

谢谢, 塞巴斯蒂安

最佳答案

这确实看起来像一个错误(可能值得报告),但问题在于您通过访问 ["state"] 将泛型参数约束到自身的方式。您实际上不需要此约束,并且可以使用 any ,当在 extends 子句中使用时,它具有“不受约束”的含义,而不是字面上的“any”。这有效:

function createModel<TModel extends ModelDefinition<any>>(modelDefinition: TModel): void {
    // ...
}

关于TypeScript——一些高级类型推断的问题;尝试为 Rematch 构建更好的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54501901/

相关文章:

html - Angular 5设置带有html转义(实体)字符的文档标题

java - 通用compareTo对不同对象类进行排序

java - 创建一个setter来提供java List实现类

ios - Switch case 语句 - 通用关联类型

Swift 的 pow() 函数不接受 Doubles 作为参数

javascript - Vuejs 实现全局确认对话框功能时遇到的问题

javascript - 如何通过索引而不是名称映射 JSON 属性

javascript - Angular 2 登录指令和 location.createComponent

javascript - Angular 中的操作系统环境变量

java - 如何将嵌套的 Scala 集合转换为嵌套的 Java 集合