tsc --watch initial build 3x slower than tsc
See original GitHub issueTypeScript Version: 3.7.0-dev.20191011, 3.6.4, 3.5.2
Search Terms: DeepReadonly slow watch mode
Code
The slowness occurs on a codebase of around 1000 files. I can’t distill it into a repro, but I can show the type that causes the slowness and an alternate type that does not.
I noticed the slowness when I replaced our implementation of DeepReadonly
with the one from ts-essentials
. One thing I should note in case it is helpful, is that in our codebase DeepReadonly
is only used about 80 times. It’s also used nested in some instances, a DeepReadonly type is included as a property of another DeepReadonly type, for example.
Here is the type from ts-essentials
:
export type Primitive = string | number | boolean | bigint | symbol | undefined | null;
/** Like Readonly but recursive */
export type DeepReadonly<T> = T extends Primitive
? T
: T extends Function
? T
: T extends Date
? T
: T extends Map<infer K, infer V>
? ReadonlyMap<K, V>
: T extends Set<infer U>
? ReadonlySet<U>
: T extends {}
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: Readonly<T>;
interface ReadonlySet<ItemType> extends Set<DeepReadonly<ItemType>> {}
interface ReadonlyMap<KeyType, ValueType> extends Map<DeepReadonly<KeyType>, DeepReadonly<ValueType>> {}
Here is ours:
export type Primitive = number | boolean | string | symbol
export type DeepReadonly<T> = T extends ((...args: any[]) => any) | Primitive
? T
: T extends _DeepReadonlyArray<infer U>
? _DeepReadonlyArray<U>
: T extends _DeepReadonlyObject<infer V>
? _DeepReadonlyObject<V>
: T
export interface _DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
export type _DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>
}
Expected behavior:
Both types, when used in our codebase would take a similar amount of time for both a tsc
and the initial build of tsc --watch
.
Actual behavior:
Our original DeepReadonly
takes about 47 seconds to build using tsc
. The initial build with tsc --watch
also takes a similar amount of time, around 49 seconds.
With the ts-essentials
version, a tsc
build takes around 48 seconds. The initial build with tsc --watch
takes anywhere from 3-5 minutes.
Playground Link:
N/A
Related Issues:
None for sure.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:51 (21 by maintainers)
These all obscure steps are things that better be done by TypeScript internally. And this is not emit-only issue, but when you have a huge type that being expanded, it will also drastically slowdown intellisense and freeze vscode
FWIW, I tracked down the bad declarations using an emit only build, and then used a file size explorer to determine which files were slowing the build down. This got my build a 3x speedup (70secs -> 20secs)
tsc -p ./tsconfig.base.json --declaration --emitDeclarationOnly --extendedDiagnostics --declarationDir ~/Temp/declarations
I used Disk Inventory X and found big files and cut them down.
Before:
After:![71001691-b54bfb80-20d5-11ea-9f69-faa5186a614e](https://user-images.githubusercontent.com/3147213/71010112-45dd0880-20e3-11ea-9fac-9afdeb60b520.png)