Repository: TypeScript
Issue: Consider supporting an array for package.json types
Labels: Suggestion,Awaiting More Feedback

## Search Terms
 package.json types

## Suggestion

Allow the package.json `"types"` field to be a list of strings.

## Use Cases

I will acknowledge that the primary use case inspiring this suggestion is a bit flimsy (which I will address below), but allowing the `"types"` field to be a list can potentially solve a current issue with monorepo development, by giving the compiler fallbacks for either the development / tooling stage or the build stage.

## Examples

Take a monorepo project structure:

```
/repo/tsconfig.base.json
/repo/package.json

/repo/packages/App/package.json
/repo/packages/App/src/tsconfig.json
/repo/packages/App/src/index.ts

/repo/packages/LibA/package.json
/repo/packages/LibA/src/tsconfig.json
/repo/packages/LibA/src/index.ts

/repo/packages/LibB/package.json
/repo/packages/LibB/src/tsconfig.json
/repo/packages/LibB/src/index.ts
```

```json
// /repo/tsconfig.base.json
{
  "compilerOptions": {
    "baseUrl": "./",
    "module": "esnext",
    "moduleResolution": "node",
    "paths": {
      "@repo/*": ["node_modules/@repo/*/src"]
    }
  }
}
```
For each packages `src/tsconfig.json`:
```json
{
  "extends": "../../../tsconfig.base.json"
}
```

"App" isn't really an issue because nothing imports it. But the libs could be used in multiple ways, and can also be published. For publishing, a lib might have a package.json file like:

```json
{
  "name": "@repo/LibA",
  "version": "0.0.1",
  "main": "index.js",
  // This is built
  "types": "index.d.ts"
}
```

With this configuration, builds work fine. However, during development, we don't want to reference a compiled definition file for types. If we make changes to a lib, we want to see those changes without having to compile and refresh any caches or a TypeScript server.

To accomplish this, we can just use a clean script to clear out any of the build artifacts during development, but there's a slight problem: Without the definition file (e.g. `/repo/packages/LibA/index.d.ts`), imports aren't exactly what we're looking for by default. For example, without the definition file, if I try to auto import, either in VSCode or WebStorm, it looks like this:

```ts
// /repo/packages/App/src/index.ts
import {Foo} from '@repo/LibA/src';

let f: Foo // Auto import triggered
```
So now I have to go trim off the `/src` b/c TS is looking for types, and isn't finding them. I'm actually not sure why it adds the `/src`, even though we have path mappings that would resolve to a shorter path. What I do know is that we can fix this during development by changing the `"types"` field:

```json
{
  "types": "src/index.ts"
}
```
According to descriptions of the module resolution algorithm and looking through the code that does this resolution, even for `DtsOnly`, TypeScript files are fine. Now auto imports will default to the expected behavior:
```ts
import {Foo} from '@repo/LibA';

let f: Foo
```
I think now it's probably obvious why I think a `"types"` array would help solve this. If types were a list, we could clean build files during development and still fallback to sources for types.

There are a lot of potential issues with this, obviously. I think the most I can probably hope for is to draw attention to yet another issue with TypeScript and monorepos. I've read through most of [this long discussion](https://github.com/microsoft/TypeScript/issues/25376), and monorepo woes are obviously something the team is aware of.

Some issues I can think of:
- It might encourage authors to export types in ways that aren't encouraged by the TS team or the community.
- If multiple type files are present, it could incur a significant performance penalty from excessive parsing and declaration merging
- It's a non-targeted solution for a very targeted problem that few people probably contend with anyways.

However, by bringing it up, I figure that the experts here will understand the implications and potential solutions on a much deeper and more intuitive level. Perhaps there is some way of supporting this without adding anything gnarly or changing the `"types"` field. Potentially a `"typesFallback"` field could be added. I don't know what's worse, honestly.

Thank you for your time.

## Checklist

My suggestion meets these guidelines:

* [&check;] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [&check;] This wouldn't change the runtime behavior of existing JavaScript code
* [&check;] This could be implemented without emitting different JS based on the types of the expressions
* [&check;] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [ ] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).