typescript - 展开运算符类型不安全

标签 typescript spread

我有一个函数应该返回某种类型,但使用扩展运算符导致它分配一个拼写错误的键。

interface State {
    fieldA: number,
    fieldB: string
}

const reducer: (state: State, action: {payload: string}) => State = (state, action) => {

    // please note that those variables are not desired
    const tmp = { ...state, feildB: action.payload }; // No compile time error, :(

    // This is too verbose... but works
    const tmp2 = Object.assign<State, Partial<State>>(state, {feildB: action.payload}) // ERROR - this is what I need
    return tmp
}
const t = reducer({fieldA: 1, fieldB: 'OK'}, {payload: 'Misspelled'}) // Misspelled
console.log("feildB", (t as any).feildB) // Misspelled
console.log("fieldB", (t as any).fieldB) // OK

有没有办法使其类型安全,同时将样板代码保持在最低限度?

Playground code HERE

最佳答案

TypeScript 正在做它应该做的事情。在您的例子中,您正在创建一个新对象 tmp,其新类型具有 3 个字段,即:

interface State {
    fieldA: number;
    fieldB: string;
}
interface Tmp {
    fieldA: string;
    fieldB: string;
    payload: string;
}

换句话说,传播运算符执行以下操作:

interface Obj {
    [key: string]: any;
}

const spread = (...objects: Obj[]) => {
    const merged: Obj = {};

    objects.forEach(obj => {
        Object.keys(obj).forEach(k => merged[k] = obj[k]);
    });

    return merged;
}

传播运算符正在为您创建一种新类型的对象;如果你想推断类型,那么你应该这样做:

// this now throws an error
const tmp: State = { ...state, feildB: action.payload };

关于typescript - 展开运算符类型不安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59129738/

相关文章:

javascript - 传播 getElementsByClassName 或 querySelectorAll 会在 TypeScript 中产生错误

r - 在R dplyr中,为什么扩展函数后面有一个单引号?

reactjs - 这是将 Prop 传递给 React 中的子组件的好方法吗?

javascript - typescript 中的 Object.freeze/Object.seal

typescript - 通过返回类型的调用签名联合缩小函数类型

angular - 类型错误 : provideModuleMap is not a function ~ NestJS

typescript - 如何修复泛型 TypeScript 函数以返回有效的推断类型?

javascript - 从 Typescript 1.6.2 中的内置数组扩展的类在使用 [] 运算符时不会更新长度

r - 如何通过 R 中的 dplyr/tidyverse 将分组行复制到列中?

javascript - 如何破译键值对的映射函数