You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Function arguments allow unknown properties when passed as variables #31412
exportinterfaceThemeVar{light: string;dark: string;}typeTheme=keyofThemeVar|{name: keyofThemeVar};functionthemed(styles: TemplateStringsArray,
...themedVars: ThemeVar[]): any[]{constprocessedThemedVars=themedVars.map(themedVar=>({ theme }: {theme: Theme})=>typeoftheme==='string'
? themedVar[theme]
: themedVar[theme.name],);returnstyles.map((string,i)=>[string,processedThemedVars[i]||'',]);}constcolors={dark: '#FFF',light: '#000',shouldFail: 0}consttest=themed` color: ${colors}; // VALID ???`;consttest2=themed` color: ${{dark: '#FFF',light: '#000',shouldFail: 0// INVALID// Object literal may only specify known properties,// and 'shouldFail' does not exist in type 'ThemeVar'.}};`;functionthemedFn(themeVar: ThemeVar){returnthemeVar;}themedFn(colors);// VALID ???themedFn({dark: '#FFF',light: '#000',shouldFail: 0// INVALID// Object literal may only specify known properties,// and 'shouldFail' does not exist in type 'ThemeVar'.});
Expected behavior:
Object literals passed as variables should fail with unknown properties just as they do when passed directly.
Actual behavior:
Object literals passed as variables allow for unknown properties.
You may easily enforce type constraints for your inputs before they are consumed to catch this type of error:
constcolors:ThemeVar={dark: '#FFF',light: '#000',shouldFail: 0// Will show error.}/* ERRORType '{ dark: string; light: string; shouldFail: number; }' is not assignable to type 'ThemeVar'. Object literal may only specify known properties, and 'shouldFail' does not exist in type 'ThemeVar'.(property) shouldFail: number*/
poseidonCore This for a library, and while it's simple enough to do that internally, it's a bad developer experience to need to import ThemeVar and repeatedly specify it manually. The actual use case is a convenience utility within styled-components:
I understand the frustration but the excess properties must be allowed; it’s not just a convenience, but actually required in a structural typing system in order to be able to express subclasses at all.
Excess is checked for in direct object literals because extra properties there are nearly always an error, but in general, if class D extends C with some extra stuff then disallowing excess properties across the board would prevent objects of type D from being assignable to C. Not very practical.
Hmm... though the more I think about it, I do wonder if the freshness checks could safely be extended... I might have an idea for a proposal. I’ll give it some thought.
siobhán (@seanmcintyre), if you are willing to export a class from a library and import it repeatedly elsewhere, then you should be willing to do the same for an interface/type used in that class. This particular practice and developer experience is common throughout most strictly typed languages.
I feel your frustration with this issue because I used to feel the same, but applying the simple pattern that I described is the only real way around this. As Ryan Cavanaugh (@RyanCavanaugh) has pointed out, this is a language feature and so we have to work with this.
Activity
RyanCavanaugh commentedon May 15, 2019
This is the intended behavior.
fatcerberus commentedon May 15, 2019
siobhán (@seanmcintyre) See https://github.com/basarat/typescript-book/blob/master/docs/types/freshness.md#freshness
poseidonCore commentedon May 16, 2019
You may easily enforce type constraints for your inputs before they are consumed to catch this type of error:
seanmcintyre commentedon May 16, 2019
poseidonCore This for a library, and while it's simple enough to do that internally, it's a bad developer experience to need to import
ThemeVarand repeatedly specify it manually. The actual use case is a convenience utility within styled-components:fatcerberus commentedon May 16, 2019
I understand the frustration but the excess properties must be allowed; it’s not just a convenience, but actually required in a structural typing system in order to be able to express subclasses at all.
Excess is checked for in direct object literals because extra properties there are nearly always an error, but in general, if
class D extends Cwith some extra stuff then disallowing excess properties across the board would prevent objects of typeDfrom being assignable toC. Not very practical.fatcerberus commentedon May 16, 2019
Hmm... though the more I think about it, I do wonder if the freshness checks could safely be extended... I might have an idea for a proposal. I’ll give it some thought.
poseidonCore commentedon May 16, 2019
siobhán (@seanmcintyre), if you are willing to export a class from a library and import it repeatedly elsewhere, then you should be willing to do the same for an interface/type used in that class. This particular practice and developer experience is common throughout most strictly typed languages.
I feel your frustration with this issue because I used to feel the same, but applying the simple pattern that I described is the only real way around this. As Ryan Cavanaugh (@RyanCavanaugh) has pointed out, this is a language feature and so we have to work with this.
typescript-bot commentedon May 18, 2019
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.