How can I get TypeScript to type-check the spread operator in React props?
up vote
2
down vote
favorite
This code properly flagged in TS:
<MyComponent nonexistentProp="foo" />
This code is not:
<MyComponent { ...{ nonexistentProp: "foo" }} />
It seems trivial for TS to check that improper props are not getting passed in - how can we enable this checking to ensure that we're passing in the expected props?
reactjs typescript static-analysis
add a comment |
up vote
2
down vote
favorite
This code properly flagged in TS:
<MyComponent nonexistentProp="foo" />
This code is not:
<MyComponent { ...{ nonexistentProp: "foo" }} />
It seems trivial for TS to check that improper props are not getting passed in - how can we enable this checking to ensure that we're passing in the expected props?
reactjs typescript static-analysis
1
I believe this is not specific to JSX and spread. This actually can be reduced toReact.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vsReact.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).
– estus
Nov 20 at 21:43
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
This code properly flagged in TS:
<MyComponent nonexistentProp="foo" />
This code is not:
<MyComponent { ...{ nonexistentProp: "foo" }} />
It seems trivial for TS to check that improper props are not getting passed in - how can we enable this checking to ensure that we're passing in the expected props?
reactjs typescript static-analysis
This code properly flagged in TS:
<MyComponent nonexistentProp="foo" />
This code is not:
<MyComponent { ...{ nonexistentProp: "foo" }} />
It seems trivial for TS to check that improper props are not getting passed in - how can we enable this checking to ensure that we're passing in the expected props?
reactjs typescript static-analysis
reactjs typescript static-analysis
asked Nov 20 at 20:20
Luke Williams
1,119826
1,119826
1
I believe this is not specific to JSX and spread. This actually can be reduced toReact.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vsReact.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).
– estus
Nov 20 at 21:43
add a comment |
1
I believe this is not specific to JSX and spread. This actually can be reduced toReact.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vsReact.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).
– estus
Nov 20 at 21:43
1
1
I believe this is not specific to JSX and spread. This actually can be reduced to
React.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vs React.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).– estus
Nov 20 at 21:43
I believe this is not specific to JSX and spread. This actually can be reduced to
React.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vs React.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).– estus
Nov 20 at 21:43
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
I suspect this type checking is subject to the same constraints as regular TypeScript code:
interface Contract {
a: string;
}
const allowed: Contract = {
a: "bc",
};
const notAllowed: Contract = {
a: "bc",
b: "dc",
};
const aboutToBeAllowed = {
a: "bc",
b: "dc",
};
const alsoAllowed: Contract = aboutToBeAllowed;
The problem shown here is that TypeScript has it's limitations, in that it's a structural type system.
It is only able to enforce the constraints that us humans think it should be doing in all cases during an object literal assignment (see notAllowed
assignment).
The alsoAllowed
case is essentially the same as the notAllowed
variant, but it works. This is because the anonymous object satisfies the Contract
constraints.
Similarly, in your TSX example, this is essentially the same behavior as regular TypeScript:
interface Props { a: string; };
const MyComponent: React.SFC<Props> = (props) => <div />;
const myCompOk1 = <MyComponent a="ab" />;
const myCompBad1 = <MyComponent a="ab" b="cd" />;
const anonPropsNoExtra = { a: "bc" };
const myCompOk2 = <MyComponent {...anonPropsNoExtra} />;
const anonPropsWithExtra = { a: "bc", b: "cd" };
const myCompOk3 = <MyComponent {...anonPropsWithExtra} />;
I don't believe it's possible for it to enforce it the way you're looking for
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I suspect this type checking is subject to the same constraints as regular TypeScript code:
interface Contract {
a: string;
}
const allowed: Contract = {
a: "bc",
};
const notAllowed: Contract = {
a: "bc",
b: "dc",
};
const aboutToBeAllowed = {
a: "bc",
b: "dc",
};
const alsoAllowed: Contract = aboutToBeAllowed;
The problem shown here is that TypeScript has it's limitations, in that it's a structural type system.
It is only able to enforce the constraints that us humans think it should be doing in all cases during an object literal assignment (see notAllowed
assignment).
The alsoAllowed
case is essentially the same as the notAllowed
variant, but it works. This is because the anonymous object satisfies the Contract
constraints.
Similarly, in your TSX example, this is essentially the same behavior as regular TypeScript:
interface Props { a: string; };
const MyComponent: React.SFC<Props> = (props) => <div />;
const myCompOk1 = <MyComponent a="ab" />;
const myCompBad1 = <MyComponent a="ab" b="cd" />;
const anonPropsNoExtra = { a: "bc" };
const myCompOk2 = <MyComponent {...anonPropsNoExtra} />;
const anonPropsWithExtra = { a: "bc", b: "cd" };
const myCompOk3 = <MyComponent {...anonPropsWithExtra} />;
I don't believe it's possible for it to enforce it the way you're looking for
add a comment |
up vote
0
down vote
I suspect this type checking is subject to the same constraints as regular TypeScript code:
interface Contract {
a: string;
}
const allowed: Contract = {
a: "bc",
};
const notAllowed: Contract = {
a: "bc",
b: "dc",
};
const aboutToBeAllowed = {
a: "bc",
b: "dc",
};
const alsoAllowed: Contract = aboutToBeAllowed;
The problem shown here is that TypeScript has it's limitations, in that it's a structural type system.
It is only able to enforce the constraints that us humans think it should be doing in all cases during an object literal assignment (see notAllowed
assignment).
The alsoAllowed
case is essentially the same as the notAllowed
variant, but it works. This is because the anonymous object satisfies the Contract
constraints.
Similarly, in your TSX example, this is essentially the same behavior as regular TypeScript:
interface Props { a: string; };
const MyComponent: React.SFC<Props> = (props) => <div />;
const myCompOk1 = <MyComponent a="ab" />;
const myCompBad1 = <MyComponent a="ab" b="cd" />;
const anonPropsNoExtra = { a: "bc" };
const myCompOk2 = <MyComponent {...anonPropsNoExtra} />;
const anonPropsWithExtra = { a: "bc", b: "cd" };
const myCompOk3 = <MyComponent {...anonPropsWithExtra} />;
I don't believe it's possible for it to enforce it the way you're looking for
add a comment |
up vote
0
down vote
up vote
0
down vote
I suspect this type checking is subject to the same constraints as regular TypeScript code:
interface Contract {
a: string;
}
const allowed: Contract = {
a: "bc",
};
const notAllowed: Contract = {
a: "bc",
b: "dc",
};
const aboutToBeAllowed = {
a: "bc",
b: "dc",
};
const alsoAllowed: Contract = aboutToBeAllowed;
The problem shown here is that TypeScript has it's limitations, in that it's a structural type system.
It is only able to enforce the constraints that us humans think it should be doing in all cases during an object literal assignment (see notAllowed
assignment).
The alsoAllowed
case is essentially the same as the notAllowed
variant, but it works. This is because the anonymous object satisfies the Contract
constraints.
Similarly, in your TSX example, this is essentially the same behavior as regular TypeScript:
interface Props { a: string; };
const MyComponent: React.SFC<Props> = (props) => <div />;
const myCompOk1 = <MyComponent a="ab" />;
const myCompBad1 = <MyComponent a="ab" b="cd" />;
const anonPropsNoExtra = { a: "bc" };
const myCompOk2 = <MyComponent {...anonPropsNoExtra} />;
const anonPropsWithExtra = { a: "bc", b: "cd" };
const myCompOk3 = <MyComponent {...anonPropsWithExtra} />;
I don't believe it's possible for it to enforce it the way you're looking for
I suspect this type checking is subject to the same constraints as regular TypeScript code:
interface Contract {
a: string;
}
const allowed: Contract = {
a: "bc",
};
const notAllowed: Contract = {
a: "bc",
b: "dc",
};
const aboutToBeAllowed = {
a: "bc",
b: "dc",
};
const alsoAllowed: Contract = aboutToBeAllowed;
The problem shown here is that TypeScript has it's limitations, in that it's a structural type system.
It is only able to enforce the constraints that us humans think it should be doing in all cases during an object literal assignment (see notAllowed
assignment).
The alsoAllowed
case is essentially the same as the notAllowed
variant, but it works. This is because the anonymous object satisfies the Contract
constraints.
Similarly, in your TSX example, this is essentially the same behavior as regular TypeScript:
interface Props { a: string; };
const MyComponent: React.SFC<Props> = (props) => <div />;
const myCompOk1 = <MyComponent a="ab" />;
const myCompBad1 = <MyComponent a="ab" b="cd" />;
const anonPropsNoExtra = { a: "bc" };
const myCompOk2 = <MyComponent {...anonPropsNoExtra} />;
const anonPropsWithExtra = { a: "bc", b: "cd" };
const myCompOk3 = <MyComponent {...anonPropsWithExtra} />;
I don't believe it's possible for it to enforce it the way you're looking for
answered Nov 21 at 5:14
Alex
1,9041415
1,9041415
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53400926%2fhow-can-i-get-typescript-to-type-check-the-spread-operator-in-react-props%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I believe this is not specific to JSX and spread. This actually can be reduced to
React.createElement<MyComponentProps>(MyComponent, { nonexistentProp: "foo" })
vsReact.createElement<MyComponentProps>(MyComponent, Object.assign({ nonexistentProp: "foo" }))
(this is what happens internally).– estus
Nov 20 at 21:43