带有扩展运算符的 TypeScript React setState

TypeScript React setState with spread operator

我有这个界面。

interface parts {
    general: boolean,
    source: boolean,
    target: boolean
}

当在 Parent 组件中初始化状态并使用该接口键入它时,TypeScript 会按预期工作。

const Parent: React.FC = () => { 
    const [parts, setParts] = useState<parts>({
        general: false,
        source: false,
        target: false,
        wrongKey: "Typescript reports problem"
    })
    
    return (
        <Child setParts={setParts} />
    )
}

但是当它传递给 child 时,TypeScript 无法按预期工作。

const Child: React.FC<{setParts: React.Dispatch<React.SetStateAction<parts>> }> =({setParts}) => { 
    setParts((parts: parts) => {
        ...parts,
        wrongKey: "Typescript doesn't report problem"
    })

    return (
        <div></div>
    )
}

对于布尔值或字符串等类型,它可以正常工作,但字典存在一些问题。

Excess 属性 检查仅在您尝试分配对象文字时触发。对于其他情况,TypeScript 仅检查对象的形状是否与请求的类型匹配。原因是当您内联传递错误形状的对象时,很可能是开发人员错误。允许这样做有什么好处?所以这是一个错字或者你想要别的东西。

但是如果你传递一个变量,它只需要检查形状是否正确,就不会有任何 运行时间问题。例如,您可以执行以下操作:

 const [parts, setParts] = useState<parts>({
        general: false,
        source: false,
        target: false,
        wrongKey: "Typescript reports problem"
    } as parts)

这样 TypeScript 将确保您传递 'something',它可以被整形为 parts。不知道有没有用,举个例子吧:)

我不确定这是否真的是您不知道传递无关 属性 的问题。我想强调一下,如果您 忘记 传递 属性 来满足所需类型的形状,TypeScript 会告诉您这一点,这很重要。

如果你真的想拒绝额外的属性,请检查这个答案:

更新 1: 为什么没有触发 excess 属性 检查,因为实际上我们 return 使用对象文字,我说 excess 属性 check 运行 在那种情况下,这有点矛盾,但是其实不是。

考虑这个例子:

type Parts = {
general: boolean;
source: boolean;
target: boolean;
}

type FunctionType = (parts: Parts) => Parts;

function ShowsError(parts: Parts): Parts {
 return {
   ...parts,
   someExtraPropertyWhichTriggerError:'Ooops'
 }
}

const myArrowFunction = (parts: Parts) => ({
  ...parts,
  someExtraPropertyWithoutError:'Why no report?:('
});


const DoesntShowError: FunctionType = myArrowFunction;

那么那里发生了什么?貌似是两个一模一样的函数,一个是箭头函数,一个是普通函数,为什么是箭头函数就没有错误呢?相同的参数,相同的 return 类型,相同的对象 returned.

关键区别在于,当我们定义箭头函数时,其 return 语句 NOT 上下文绑定到部件。 TypeScript 无法知道它要用在什么地方。所以它为其 return 类型生成一个形状,然后继续。 然后我们将它分配给 DoesntShowError 这需要我们分配给定类型的函数。而箭头函数满足了这个要求。我想就这些了,希望对你有帮助。