When I have this:
interface PropTypes {
user?: {
name?: string,
age?: number
}
}
const Comp = (props: PropTypes) => ...
Why this works:
const user = {
random: 3,
name: 'test'
}
<Comp user={user} /> // works
But this does not (moved value from variable to here):
<Comp user={{ random: 3, name: 'test' }} /> // does not work
Also when I delete all known properties from user it does not work anymore:
const user = {
random: 3
}
<Comp user={user} /> // does not work
I want to know why it works like this. Why it accepts the "random" prop, that is unknown for him when it is in variable. Why variable type has different behaviour than directly passing prop? Is there any way to allow only exact props without giving type each time to the variable?
CodePudding user response:
This has to do with Typescript's Excess Property Checking.
Structural Type System: TypeScript is fine with having extra properties as long as you provide a type with its’ required properties.
When TypeScript encounters object literal in assignments or when passed as an argument to functions it triggers an action called Excess Property Checking. Contrary to structural typing, it check whether the object has the exact properties.
One interesting behavior is with “Weak Types” — types which all their fields are marked as Optional. In this case the excess property checking an action takes place even when assigning intermediate variable.
You can read more at this link.
Case 1 - Structural Type System
const user = {
random: 3,
name: 'test'
}
<Comp user={user} /> // works
In this case the type of user
is inferred as:
{
random: number;
name: string;
}
This type is compatible with PropTypes
, so no error.
Case 2 - Excess Property Checking
Passing object literal in assignments:
<Comp user={{ random: 3, name: 'test' }} /> // does not work
In this case random
is not a valid property for type PropTypes
, so typescript tells you adding random
is an error.
Object literal may only specify known properties, and 'random' does not exist in type '{ name?: string | undefined; age?: number | undefined; }'
Case 3 - Weak Types
const user = {
random: 3
}
<Comp user={user} /> // does not work
In this case typescript inferred the type of user as:
{
random: number;
}
Also in this case random
is an invalid property for PropTypes
, so this is an error.