Relate control flow to conditional types in return types
## Search Terms control flow conditional return type cannot assign extends ## Suggestion Developers are eager to use conditional types in functions, but this is unergonomic: ```ts type Person = { name: string; address: string; }; type Website = { name: string; url: URL }; declare function isWebsite(w: any): w is Website; declare function isPerson(p: any): p is Person; function getAddress<T extends Person | Website>(obj: T): T extends Person ? string : URL { if (isWebsite(obj)) { // Error return obj.url; } else if (isPerson(obj)) { // Another error return obj.address; } throw new Error('oops'); } ``` The errors here originate in the basic logic: > `obj.url` is a `URL`, and a `URL` isn't a `T extends Person ? string : URL` By some mechanism, this function should *not* have an error. ## Dead Ends The current logic is that all function return expressions must be assignable to the explicit return type annotation (if one exists), otherwise an error occurs. A tempting idea is to change the logic to "Collect the return type (using control flow to generate conditional types) and compare that to the annotated return type". This would be a bad idea because the function implementation would effectively reappear in the return type: ```ts function isValidPassword<T extends string>(s: T) { if (s === "very_magic") { return true; } return false; } // Generated .d.ts function isValidPassword<T extends string>(s: T): T extends "very_magic" ? true :
Posted by RyanCavanaugh on Oct 9, 2019, 8:41 PM
Tags
Related issues
- struct's lifetime requirements can be bypassed via covariant field assignment
- Proposal to Reorganize the Moderation Team and Review Moderation Policies
- Progressive FPS degradation appears to be related to dota2.com — blocking the domain prevents the performance loss
- proposal: container/...: generic collection types
- Better Custom Endpoint BYOK
- A concrete policy for backward compatibility until Godot 5.0
Raise real-world problems, find people facing the same issue, and discuss solutions.3,500 issues0 comments
github (Other)
struct's lifetime requirements can be bypassed via covariant field assignment
Proposal to Reorganize the Moderation Team and Review Moderation Policies
Progressive FPS degradation appears to be related to dota2.com — blocking the domain prevents the performance loss
proposal: container/...: generic collection types
Better Custom Endpoint BYOK
A concrete policy for backward compatibility until Godot 5.0
New MTP models not supported
Tracking: 429 / Capacity Issues
Relate control flow to conditional types in return types
## Search Terms control flow conditional return type cannot assign extends ## Suggestion Developers are eager to use conditional types in functions, but this is unergonomic: ```ts type Person = { name: string; address: string; }; type Website = { name: string; url: URL }; declare function isWebsite(w: any): w is Website; declare function isPerson(p: any): p is Person; function getAddress<T extends Person | Website>(obj: T): T extends Person ? string : URL { if (isWebsite(obj)) { // Error return obj.url; } else if (isPerson(obj)) { // Another error return obj.address; } throw new Error('oops'); } ``` The errors here originate in the basic logic: > `obj.url` is a `URL`, and a `URL` isn't a `T extends Person ? string : URL` By some mechanism, this function should *not* have an error. ## Dead Ends The current logic is that all function return expressions must be assignable to the explicit return type annotation (if one exists), otherwise an error occurs. A tempting idea is to change the logic to "Collect the return type (using control flow to generate conditional types) and compare that to the annotated return type". This would be a bad idea because the function implementation would effectively reappear in the return type: ```ts function isValidPassword<T extends string>(s: T) { if (s === "very_magic") { return true; } return false; } // Generated .d.ts function isValidPassword<T extends string>(s: T): T extends "very_magic" ? true :
Comments (0)
No comments yet. Start the discussion.