How can I get TypeScript to type-check the spread operator in React props?












2














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?










share|improve this question


















  • 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
















2














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?










share|improve this question


















  • 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














2












2








2







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?










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 at 20:20









Luke Williams

1,197928




1,197928








  • 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














  • 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








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












1 Answer
1






active

oldest

votes


















1














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






share|improve this answer





















  • Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
    – Luke Williams
    Dec 3 at 19:14











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















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

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














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






share|improve this answer





















  • Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
    – Luke Williams
    Dec 3 at 19:14
















1














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






share|improve this answer





















  • Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
    – Luke Williams
    Dec 3 at 19:14














1












1








1






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






share|improve this answer












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







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 5:14









Alex

1,9841415




1,9841415












  • Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
    – Luke Williams
    Dec 3 at 19:14


















  • Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
    – Luke Williams
    Dec 3 at 19:14
















Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
– Luke Williams
Dec 3 at 19:14




Ok - interesting, thank you for the background. I'm able to get what I need by refactoring a bit to type-check the object before spreading it into the props.
– Luke Williams
Dec 3 at 19:14


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen