Conversation
|
Where'd we end up with mapped conditional types w.r.t |
Does that make sense (is this derived from something else)? If |
|
@weswigham No, that probably doesn't make sense. We should be similar to |
|
@RyanCavanaugh Do you mean the behavior of |
|
|
||
| // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions. | ||
| if (returnType && maybeTypeOfKind(returnType, TypeFlags.Any | TypeFlags.Void)) { | ||
| if (returnType && maybeTypeOfKind(returnType, TypeFlags.AnyOrUnknown | TypeFlags.Void)) { |
There was a problem hiding this comment.
I think a function returning an explicit unknown should probably have return values? Otherwise you should've written void or undefined, right?
There was a problem hiding this comment.
Not sure about that. undefined is in the domain of unknown (just like it is in the domain of any) and that's really what should guide us here.
There was a problem hiding this comment.
Hm. Fair. Do we handle unions with undefined in accordance with that, then?
There was a problem hiding this comment.
We do, but with a few wrinkles. If the return type annotation includes void, any, or unknown we don't require any return statements. Otherwise, if the return type includes undefined we require at least one return statement somewhere, but don't require return statements to have expressions and allow the end point of the function to be reachable. Otherwise, we require a return statement with an expression at every exit point.
| >T : T | ||
|
|
||
| boom: T extends any ? true : true | ||
| >boom : T extends any ? true : true |
There was a problem hiding this comment.
why did this type collapse to true?
There was a problem hiding this comment.
I changed this to eagerly resolve to true when the extends type is any or unknown (since it always will be).
There was a problem hiding this comment.
Ah, but what about T extends any ? { x: T } : never - that needs to distribute.
There was a problem hiding this comment.
Hmm, yes, I suppose we can only optimize when the conditional type isn't distributive.
There was a problem hiding this comment.
There's a better check (than just distributivity) that I have an outstanding PR for: instantiate the check type (and infer types) in the true/false types with wildcards. If the instantiation isn't the input type, you can't simplify. If it is, you can. (Since the type isn't affected by instantiation)
The BaseController state now uses `unknown` rather than `any` as the type for state properties. `unknown` is more type-safe than `any` in cases like this where we don't know what type to expect. See here for details [1]. This was suggested by @rekmarks during review of #362 [2]. [1]: microsoft/TypeScript#24439 [2]: #362 (comment)
* Use `unknown` rather than `any` for BaseController state The BaseController state now uses `unknown` rather than `any` as the type for state properties. `unknown` is more type-safe than `any` in cases like this where we don't know what type to expect. See here for details [1]. This was suggested by @rekmarks during review of #362 [2]. [1]: microsoft/TypeScript#24439 [2]: #362 (comment) * Use type alias for controller state rather than interface The mock controller state in the base controller tests now uses a type alias for the controller state rather than an interface. This was required to get around an incompatibility between `Record<string, unknown>` and interfaces[1]. The `@typescript-eslint/consistent-type-definitions` ESLint rule has been disabled, as this problem will be encountered fairly frequently. [1]: microsoft/TypeScript#15300 (comment)
* Use `unknown` rather than `any` for BaseController state The BaseController state now uses `unknown` rather than `any` as the type for state properties. `unknown` is more type-safe than `any` in cases like this where we don't know what type to expect. See here for details [1]. This was suggested by @rekmarks during review of #362 [2]. [1]: microsoft/TypeScript#24439 [2]: #362 (comment) * Use type alias for controller state rather than interface The mock controller state in the base controller tests now uses a type alias for the controller state rather than an interface. This was required to get around an incompatibility between `Record<string, unknown>` and interfaces[1]. The `@typescript-eslint/consistent-type-definitions` ESLint rule has been disabled, as this problem will be encountered fairly frequently. [1]: microsoft/TypeScript#15300 (comment)
* Use `unknown` rather than `any` for BaseController state The BaseController state now uses `unknown` rather than `any` as the type for state properties. `unknown` is more type-safe than `any` in cases like this where we don't know what type to expect. See here for details [1]. This was suggested by @rekmarks during review of #362 [2]. [1]: microsoft/TypeScript#24439 [2]: #362 (comment) * Use type alias for controller state rather than interface The mock controller state in the base controller tests now uses a type alias for the controller state rather than an interface. This was required to get around an incompatibility between `Record<string, unknown>` and interfaces[1]. The `@typescript-eslint/consistent-type-definitions` ESLint rule has been disabled, as this problem will be encountered fairly frequently. [1]: microsoft/TypeScript#15300 (comment)
This PR adds a new top type
unknownwhich is the type-safe counterpart ofany. Anything is assignable tounknown, butunknownisn't assignable to anything but itself andanywithout a type assertion or a control flow based narrowing. Likewise, no operations are permitted on anunknownwithout first asserting or narrowing to a more specific type.Note that this PR is technically a breaking change since
unknownbecomes a reserved type name.Fixes #10715.