Skip to content

tsc --watch initial build 3x slower than tsc #34119

Open
@aaronjensen

Description

@aaronjensen

TypeScript 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.

Metadata

Metadata

Assignees

Labels

Domain: PerformanceReports of unusually slow behaviorFix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions