简体   繁体   English

TypeScript 带有扩展运算符的 React setState

[英]TypeScript React setState with spread operator

I have this interface.我有这个界面。

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

When init state in Parent component and type it with that interface, TypeScript works as expected.当在父组件中初始化 state 并使用该界面键入它时,TypeScript 将按预期工作。

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

But when it pass to child, TypeScript doesn't work as expected.但是当它传递给孩子时,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>
    )
}

With types, like boolean or string, it works as should, but there is some problem with dictionary.对于类型,如 boolean 或字符串,它可以正常工作,但字典存在一些问题。

Excess property check only triggered when you try to assign an object literal.仅当您尝试分配 object 文字时才会触发多余的属性检查。 For other cases TypeScript only checks if the shape of object matches with the requested type.对于其他情况,TypeScript 仅检查 object 的形状是否与请求的类型匹配。 The reasoning is that it is most likely a developer error when you pass a wrong shaped object inlined.原因是当您内联传递错误形状的 object 时,很可能是开发人员错误。 What could be the benefit to allow that?允许这样做有什么好处? So it is a typo or you want something else.所以这是一个错字,或者你想要别的东西。

But if you pass a variable, it only has to check if shape is ok, there can't be really any runtime issue.但是如果你传递一个变量,它只需要检查形状是否正确,就不会有任何运行时问题。 You can do, for example, the following:例如,您可以执行以下操作:

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

That way TypeScript will make sure you pass 'something' which can be shaped as parts .这样 TypeScript 将确保您传递可以成型为parts的“东西”。 Don't know if it is useful, tho, consider it just as an example:)不知道有没有用,举个例子吧:)

I'm not sure if this is really an issue that you are not aware about passing an extraneous property.我不确定这是否真的是您不知道传递无关属性的问题。 I would like to stress if you forgot to pass a property to satisfy the shape of the required type, TypeScript will tells you that, and that is what important.我想强调的是,如果您忘记传递一个属性来满足所需类型的形状,TypeScript 会告诉您这一点,这很重要。

If you really want to deny extra properties, please check this answer: Is it possible to restrict TypeScript object to contain only properties defined by its class?如果你真的想拒绝额外的属性,请检查这个答案: Is it possible to restrict TypeScript object to contain only properties defined by its class?

UPDATE 1: Why excess property check is not triggered, as actually we return with an object literal and I said excess property check run in those case, this is kinda a contradiction, but not, actually.更新 1:为什么没有触发多余的属性检查,因为实际上我们返回了一个 object 文字,我说在这种情况下会运行多余的属性检查,这有点矛盾,但实际上不是。

Consider this example:考虑这个例子:

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;

So what is happening there?那么那里发生了什么? Looks like two identical function, one is arrow, one is normal, why there is no error in case of arrow function?貌似两个一模一样的function,一个是箭头,一个是正常的,为什么箭头function就没有错误? Same arguments, same return type, same object returned.相同的 arguments,相同的返回类型,相同的 object 返回。

The key difference is, when we define our arrow function its return statement NOT contextually binded to Parts.关键区别在于,当我们定义箭头 function 时,它的返回语句没有上下文绑定到部件。 TypeScript can't know where it is going to be used. TypeScript不知道要用在什么地方。 So its generate a shape for its return type, and go on.因此它为其返回类型生成一个形状,并在 go 上。 Then we assign it to DoesntShowError which requires us assign a function with a given type.然后我们将它分配给DoesntShowError ,这要求我们分配给定类型的 function。 And the arrowfunction satisfy that requirement.而箭头函数满足了这个要求。 Thats all, I think, hope it helps.我想就这些,希望对你有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM