Repository: TypeScript
Issue: Allow for creating more types using the type checker
Labels: Suggestion,Awaiting More Feedback

# Suggestion

Add methods like these to the TypeChecker:
```
checker.getIntersectionType(types: readonly Type[]): Type;
checker.createLiteralType(value: number | string): Type;
checker.createTupleType(types: readonly Type[]): Type;
```

## 🔍 Search Terms

typechecker create intersection type
typechecker create tuple type
typechecker create literal type

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] 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](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

Add functions to the TypeChecker, similar to `createArrayType` and `getUnionType` to allow for more easily using these types in things like lint rules.

`getIntersectionType` would be very similar to `getUnionType`, except that instead of creating `A | B | C` it would create `A & B & C`.

`createLiteralType` would be used to create a type such as `""`, `"reduce"`, `0`, `5,` etc. So far I haven't found an existing way to create these basic types. I'm not sure if "literal type" is a good name for this, but I don't know what the better one would be.

`createTupleType` would create a tuple with the passed-in types at the various positions. For example, `checker.createTupleType(checker.getStringType(), checker.getStringType(), checker.getNumberType())` would give the type `[string, string, number]`.

## 📃 Motivating Example

`getIntersectionType` would be useful for checking whether a comparison would ever make sense. If you have an `assertEqual(a: unknown, b: unknown)` function, your lint rule could check the inferred types of the arguments. If the intersection type is `never`, then you would know that the two values could never be equal, so this call is invalid. It's not effective to just check whether each one is assignable to the other, since it should be valid for `a` to be `number | undefined` while `b` is `number | null`.

`createLiteralType` would be useful for, among other things, checking if a value can be falsey or not. If you have an [Ember computed property](https://api.emberjs.com/ember/3.28/functions/@ember%2Fobject%2Fcomputed/and) of `@and('a', 'b')`, it's possible to determine what types A and B are. The possible types of the result are the possible falsey values of 'this.a' and all possible values of 'this.b' (unless 'this.a' can never be falsey). If `createLiteralType` existed, then after determining the type for `this.a` we could check `checker.isTypeAssignableTo(checker.createLiteralType(''), typeOfA)` to know whether we need to include `''` as a possible type of the result.

`createTupleType` would be useful for determining whether the value of the [collect](https://api.emberjs.com/ember/3.28/functions/@ember%2Fobject%2Fcomputed/collect) computed property can be assigned to a particular type. If you have `@collect('a', 'b', c')`, you would get the tuple `[this.a, this.b, this.c]`. Perhaps this is ultimately `[string, string, number]` However, it's possible that that this was declared to be assigned to is `[string, string, ...number]`. It's very difficult to use the type checker to figure out what the type of the rest parameter is, or at least I couldn't. But with `createTupleType` it would be easy.

## 💻 Use Cases

I mainly want to use this for lint rules, as expressed in the motivating examples. The workarounds that I've used so far have been to make the rules a lot more lenient than I would like, since there are many places where it's impossible for me to infer whether a type makes sense or not.