4 ms·
The first example doesn't bother me and I think it's a weak argument. TypeScript allows literals[1] as types[0] so it is trying to use the object as a type. Th
by leetrout 7y ago
The first example doesn't bother me and I think it's a weak argument. TypeScript allows literals[1] as types[0] so it is trying to use the object as a type.
The correct use of:
printDog({
breed: "Airedale",
age: 3
})
is to explicitly cast it:
printDog({
breed: "Airedale",
age: 3
} as Dog)
[0] https://www.typescriptlang.org/play/index.html?ssl=1&ssc=1&pln=15&pc=2#code/JYOwLgpgTgZghgYwgAgGIHt3IN4ChkHIyYAUARnFAFzIBEFUtAlDQM5hSgDmA3PocXTlKNenABezNh259CRUg1FluU5O04heuAL65cAegPIAculwwAriARhg6EMgAOmsBiEwa7pjmT8CCA6s6AA2EAB0IehcJDDhgiS0gsxMuvpGyACaEKwW1rb2ji6gbpgA4pgAJrFemD7YfvKBIMFhkdGx8aRijEypOkA https://www.typescriptlang.org/play/index.html?ssl=1&ssc=1&p...
[1] https://www.typescriptlang.org/docs/handbook/advanced-types.html#string-literal-types https://www.typescriptlang.org/docs/handbook/advanced-types....
- felixfbecker 7y agoCasting can hide errors. It's better to assign it to a variable first that has a type declaration. const dog: Dog = { breed: "Airedale", age: 3 } printDog(dog) An IIFE is safe too: printDog(((): Dog => ({ breed: "Airedale", age: 3 })())
- BigJono 7y agoYeah and both of those are less readable, and used everywhere add up to a really crap code base relative to the same code in plain JS.
- horseman 7y agoYah, pojs is so much nicer because when you mistype breed as bred you get to debug the issue at runtime for a while changing things that are irrelevant when TS could have told you immediately
- johnghanks 7y agoI would absolutely reject a PR with the IIFE.
- jahewson 7y agoActually this cast is safe in TypeScript, additional variables are unnecessary. The statement ‘const d: Dog’ and the expression ‘d as Dog’ are equivalent w.r.t. type safety. The compiler will error in both cases the if the value is not a Dog.
- agentcooper 7y agoThis is not correct. Following example is valid in strict TypeScript: interface Dog { breed: string; } const dog = {} as Dog; console.log(dog.breed); Using `as` is very unsafe in TypeScript. I've collected more quirks of `as` in this playground: https://www.typescriptlang.org/play/index.html#code/PTAEAMEsGd1AzArgOwMYBdIHtmgLYCGAnqADZZYDW0o0kppRANKAEaLqgrxYBO6KAugCmjUOgAWw3sNAxQyLKADuxcUpkAHXlgAmiVLMjoAUCFAEaBUJsQzxRTbNLCAbqNCoc0dLwOYcADozMABlYVk8PiNkENAJdHRNaAAuEABzYwlEVkCvPGA8SFQdaCx4dGAAFUdhUJLITUqYaERhaGAAdgAWAA4ARgBiFrb8vGFkdABabv6AVgGAZkWABgA2YKQ0ANwYAB4qgD4AClcCUjaU0CqASiuq0ABvE1BQGQFeXDOL4QBuEwAviYTOhaqAAGI4TgAXlAACJSJB0gk4aAAD7w8a6SCIPCojFw1hYUi6OH-EyQSbSeAEQygAAK0jKuGer3gkF4PgAcgRxlcfLxKel-kC4gBJXBuaQkVCWWTKKS4cCWOA0+g0dBKWXoVASCy4LCsVzYRAasHSHS8JhxKCwGw6fSGGi6doc4S6NjCCQEY18YKoUiWGgAYSeL1o6CEslhrNetH6AH1LFdHgCLDRGZycNa4-GEzArvtM8yTqmbtbw69oAAmJOpUAAbQRSJRLDhynQ8DhAF106AAIK8XjEPaQyaHHNxmv5+v7MfoBvdk5NxHI9Bwtsdrvd8vA3PQRZ1q7tzuoywQqGTquHgtyaCjqEnE9dm7hgEikxAA https://www.typescriptlang.org/play/index.html#code/PTAEAMEs...
- lucasmullens 7y agoThe article is just describing quirks, not arguing against them. Specifically for the first example they said "I think that the TypeScript stance here isn’t wrong".
- mekster 7y agoCasting is as bad as using "any". You can make the compiler think anything you throw at it as that type and you can get bitten at runtime.
- alexcole 7y agoThats not 100% true in TypeScript. TypeScript actually only allows "up-casts" and "down-cast" (but if the type is neither a supertype nor a subtype the compiler will throw an error).
- nojvek 7y agoThat’s my understanding too. You just can’t cast types wily Nily.
- seanmcdirmid 7y agoYa, I often have to write “this as any as T” because I’m using T as a self type.
- jahewson 7y agoNope. This is not how casting works in TypeScript. To get an unsafe cast you have to go via the ‘any’ or ‘unknown’ types. e.g. ‘foo as unknown as Dog’
- okbake 7y agoThere are a few casts that are allowed that I would consider unsafe, particularly around unions of literals or using empty object literals: // No error here type Animal = 'dog' | 'cat'; const notAnimal = 'couch' as Animal; // No error here either type Food = { isSpicy: boolean }; const empty = {} as Food; https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAggdgSwLYEMA2UC8UDkATAewHMcoAfXAYxWFIpwCMIUAnHAbgChOB6HqAGII4ETpQJwAzsCgAPAFyxEqDNnzEOvfgFEWLAiygpJUCLMiVgEPGInSoIRfGTosVAgFdKAC018oAHIEpnoGUAweMh5SKABmouJSMgBebjjiXr5GJs4qXFoAtEXFJaVl5RUF3MJWLLEolNACBAR4UADenFBQwkQs1ggQcMCSitIsvQDaALpcAL7c-kIitklQYAjJySiKza1u7T1wfQNDI4qTOJIoXhA4ADS4kGCQ+og401BzXP66+obGUzmCCWayrew+BBoBC7FptbDtb5aQLBCChQwRKIxeLgmRgYzAFAHObZQRw9hAA https://www.typescriptlang.org/play/index.html#code/C4TwDgpg...
- Kinrany 7y agoCasting may hide errors and is unnecessary in this case: `as const` will work just as well.
- nojvek 7y agoWhy would casting hide errors?
- IggleSniggle 7y agoIn the simple case, if it could be Dog|Cat and you cast as Dog but you get a Cat, and TS could have told you about the error if it hadn't been forced to treat it as Dog. This can be fixed by having your types be derived by runtime validation.
- potatoz2 7y agoThe correct use is to remove the `age` property in this case: if you're not keeping a reference to the object or that property and the called function cannot use it, why have it in the first place?
- alexcole 7y agoThat’s not always true. If you are going to print the object to the console or send it in a network request it’s possible that the additional property is important.
- wvenable 7y agoBut then it should be in the type signature of the object. TypeScript is signalling this as an error because it's a literal passed directly to the function and that property (theoretically) can never be used because it wasn't declared.