Suggestion
🔍 Search Terms
Automatic generic parameter
Generic type self reference
Generic Self keyword
Infer Self
Exclude from any
✅ Viability Checklist
My suggestion meets these guidelines:
[x] (I think) This wouldn't be a breaking change in existing TypeScript/JavaScript code
[x] (if done right) This wouldn't change the runtime behavior of existing JavaScript code
[x] This could be implemented without emitting different JS based on the types of the expressions
[x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
[x] This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
Instead of writing
type DoesTheThing<T> = T extends Something<T> ? T : never
and then
const something = aLongVariableName as DoesTheThing<typeof aLongVariableName>
it would be nice to have a way to infer the generic type in these instances.
Like this:
type DoesTheThing = infer Self extends Something<Self> ? Self : never
which could then be used like this:
const something: DoesTheThing = aLongVariableName
With the risk of being off-topic another thing that would be nice, albeit not as nice as the above, is the ability to Exclude from any.
type NotAString = Exclude<any, string> // anything that is not a string
I have three variations of my main suggestion, infer Self, that carry varying risks:
- (least risk) what I've already mentioned.
infer Self has to be in the beginning of the type definition.
- (low or no risk) You don't have to write Self but can write any name as long as it's in the start of the expression.
- (most risky) You have to write Self (or another keyword) but you can use the keyword in other places as well.
📃 Motivating Example
const aString = "some string"
const aFunction = (test: string) => "string"
// This is how we have to do it now
export type NotFunction<T> = Exclude<T, (...args: any) => any>
const old1 = aString as NotFunction<typeof aString>
// ^"some string"
const old2 = aFunction as NotFunction<typeof aFunction>
// ^never
// Least risky change
export type NiceNotFunction = infer Self extends Exclude<Self, (...args: any) => any> ? Self : never
// Maybe more risky (?)
export type AlsoNiceNotFunction = infer ThisIsAlsoSelf extends Exclude<ThisIsAlsoSelf, (...args: any) => any> ? Self : never
const new1: NiceNotFunction = aString
// ^ Should extend string but is any currently
const new2: NiceNotFunction = aFunction
// ^ Should be never but is any currently
// Most risky/difficult change.
// InferSelf would be overrideable so that it doesn't mess up old codebases.
// It could also be a different keyword that would be a syntax error before this change,
// for example by including a space.
export type NicerNotFunction = Exclude<InferSelf, (...args: any) => any>
const new3: NicerNotFunction = aString
// ^ Should extend string but is any currently
const new4: NicerNotFunction = aFunction
// ^ Should be never but is any currently
💻 Use Cases
Google jsonable typescript to get lots of examples, the top result being this. There's also been another typescript suggestion to add JSON as a default type.
In the article, the author suggests doing this:
type JSONValue =
| string
| number
| boolean
| JSONObject
| JSONArray;
interface JSONObject {
[x: string]: JSONValue;
}
interface JSONArray extends Array<JSONValue> { }
This works but it's a bit verbose for what I wanted. I also wanted to allow undefined and null, and in that case basically anything can be JSON serialized except for functions and symbols if I'm not mistaken.
So I went on to google on how to make a NotFunction type. This was the top result, and they suggest doing this:
type NotFunction<T> = T extends Function ? never : T;
Which brings me to what I've already said.
Suggestion
🔍 Search Terms
Automatic generic parameter
Generic type self reference
Generic Self keyword
Infer Self
Exclude from any
✅ Viability Checklist
My suggestion meets these guidelines:
[x] (I think) This wouldn't be a breaking change in existing TypeScript/JavaScript code
[x] (if done right) This wouldn't change the runtime behavior of existing JavaScript code
[x] This could be implemented without emitting different JS based on the types of the expressions
[x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
[x] This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
Instead of writing
and then
it would be nice to have a way to infer the generic type in these instances.
Like this:
which could then be used like this:
With the risk of being off-topic another thing that would be nice, albeit not as nice as the above, is the ability to Exclude from any.
I have three variations of my main suggestion, infer Self, that carry varying risks:
infer Selfhas to be in the beginning of the type definition.📃 Motivating Example
💻 Use Cases
Google
jsonable typescriptto get lots of examples, the top result being this. There's also been another typescript suggestion to add JSON as a default type.In the article, the author suggests doing this:
This works but it's a bit verbose for what I wanted. I also wanted to allow undefined and null, and in that case basically anything can be JSON serialized except for functions and symbols if I'm not mistaken.
So I went on to google on how to make a NotFunction type. This was the top result, and they suggest doing this:
Which brings me to what I've already said.