microsoft / microsoft/TypeScript

[PERFORMANCE]: TS takes several seconds to validate types resulting in poor DX

Offen
#54,939 3 Kommentare 2 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Needs More Info
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

Bug Report

🔎 Search Terms
🕗 Version & Regression Information
  • This is a slow type verification leading to bad DX.
⏯ Playground Link

Playground link with relevant code

Related issue: https://github.com/drizzle-team/drizzle-orm/issues/870

💻 Code
// We can quickly address your report if:
//  - The code sample is short. Nearly all TypeScript bugs can be demonstrated in 20-30 lines of code!
//  - It doesn't use external libraries. These are often issues with the type definitions rather than TypeScript bugs.
//  - The incorrectness of the behavior is readily apparent from reading the sample.
// Reports are slower to investigate if:
//  - We have to pare too much extraneous code.
//  - We have to clone a large repo and validate that the problem isn't elsewhere.
//  - The sample is confusing or doesn't clearly demonstrate what's wrong.

I understand that this issue uses an external library, drizzle which is the source of performance problems. However, I think it would be useful for the TS team to see how people use types in real world and to see if either the drizzle team can fix the types to be better performant or the TS team can do something to better handle the use cases used by drizzle.

import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';

/**
 * This is a reproduction of slow TypeScript type validation with Drizzle.
 *
 * Steps to reproduce:
 * 1. Change "EDIT THIS" line and change `2` to `"2"` (add qoutes around the number)
 *    and save the file
 * 2. Because we have changed number to string the TS will now underline the line as
 *    being invalid.
 * 3. Go back and forth between the `2` and `"2"` and notice that there is a several
 *    second delay everytime you change source code and TS either has to add or remove
 *    the red underline. (TS Error)
 * 4. Once you establish a beseline feel to how long it takes TS to add/removo an error,
 *    comment out the `delayCount`/`latencyCount` block and repeat the steps
 * 5. Notice that now the add/remove error is instant.
 */

const x: number = 2; // EDIT THIS

export const edgeTable = sqliteTable('edges', {
  id: integer('id').primaryKey(),
  manifestHash: text('manifest_hash').notNull(),
  from: text('from'),
  to: text('to').notNull(),
  interaction: integer('interaction').notNull(),

  // COMMENT OUT THE LINES BELOW
  //////////////////////////////
  // START

  delayCount00: integer('delay_count_00').notNull(),
  delayCount01: integer('delay_count_01').notNull(),
  delayCount02: integer('delay_count_02').notNull(),
  delayCount03: integer('delay_count_03').notNull(),
  delayCount04: integer('delay_count_04').notNull(),
  delayCount05: integer('delay_count_05').notNull(),
  delayCount06: integer('delay_count_06').notNull(),
  delayCount07: integer('delay_count_07').notNull(),
  delayCount08: integer('delay_count_08').notNull(),
  delayCount09: integer('delay_count_09').notNull(),
  delayCount10: integer('delay_count_10').notNull(),
  delayCount11: integer('delay_count_11').notNull(),
  delayCount12: integer('delay_count_12').notNull(),
  delayCount13: integer('delay_count_13').notNull(),
  delayCount14: integer('delay_count_14').notNull(),
  delayCount15: integer('delay_count_15').notNull(),
  delayCount16: integer('delay_count_16').notNull(),
  delayCount17: integer('delay_count_17').notNull(),
  delayCount18: integer('delay_count_18').notNull(),
  delayCount19: integer('delay_count_19').notNull(),
  delayCount20: integer('delay_count_20').notNull(),
  delayCount21: integer('delay_count_21').notNull(),
  delayCount22: integer('delay_count_22').notNull(),
  delayCount23: integer('delay_count_23').notNull(),
  delayCount24: integer('delay_count_24').notNull(),
  delayCount25: integer('delay_count_25').notNull(),
  delayCount26: integer('delay_count_26').notNull(),
  delayCount27: integer('delay_count_27').notNull(),
  delayCount28: integer('delay_count_28').notNull(),
  delayCount29: integer('delay_count_29').notNull(),
  delayCount30: integer('delay_count_30').notNull(),
  delayCount31: integer('delay_count_31').notNull(),
  delayCount32: integer('delay_count_32').notNull(),
  delayCount33: integer('delay_count_33').notNull(),
  delayCount34: integer('delay_count_34').notNull(),
  delayCount35: integer('delay_count_35').notNull(),
  delayCount36: integer('delay_count_36').notNull(),
  delayCount37: integer('delay_count_37').notNull(),
  delayCount38: integer('delay_count_38').notNull(),
  delayCount39: integer('delay_count_39').notNull(),
  delayCount40: integer('delay_count_40').notNull(),
  delayCount41: integer('delay_count_41').notNull(),
  delayCount42: integer('delay_count_42').notNull(),
  delayCount43: integer('delay_count_43').notNull(),
  delayCount44: integer('delay_count_44').notNull(),
  delayCount45: integer('delay_count_45').notNull(),
  delayCount46: integer('delay_count_46').notNull(),
  delayCount47: integer('delay_count_47').notNull(),
  delayCount48: integer('delay_count_48').notNull(),
  delayCount49: integer('delay_count_49').notNull(),
  latencyCount00: integer('latency_count_00').notNull(),
  latencyCount01: integer('latency_count_01').notNull(),
  latencyCount02: integer('latency_count_02').notNull(),
  latencyCount03: integer('latency_count_03').notNull(),
  latencyCount04: integer('latency_count_04').notNull(),
  latencyCount05: integer('latency_count_05').notNull(),
  latencyCount06: integer('latency_count_06').notNull(),
  latencyCount07: integer('latency_count_07').notNull(),
  latencyCount08: integer('latency_count_08').notNull(),
  latencyCount09: integer('latency_count_09').notNull(),
  latencyCount10: integer('latency_count_10').notNull(),
  latencyCount11: integer('latency_count_11').notNull(),
  latencyCount12: integer('latency_count_12').notNull(),
  latencyCount13: integer('latency_count_13').notNull(),
  latencyCount14: integer('latency_count_14').notNull(),
  latencyCount15: integer('latency_count_15').notNull(),
  latencyCount16: integer('latency_count_16').notNull(),
  latencyCount17: integer('latency_count_17').notNull(),
  latencyCount18: integer('latency_count_18').notNull(),
  latencyCount19: integer('latency_count_19').notNull(),
  latencyCount20: integer('latency_count_20').notNull(),
  latencyCount21: integer('latency_count_21').notNull(),
  latencyCount22: integer('latency_count_22').notNull(),
  latencyCount23: integer('latency_count_23').notNull(),
  latencyCount24: integer('latency_count_24').notNull(),
  latencyCount25: integer('latency_count_25').notNull(),
  latencyCount26: integer('latency_count_26').notNull(),
  latencyCount27: integer('latency_count_27').notNull(),
  latencyCount28: integer('latency_count_28').notNull(),
  latencyCount29: integer('latency_count_29').notNull(),
  latencyCount30: integer('latency_count_30').notNull(),
  latencyCount31: integer('latency_count_31').notNull(),
  latencyCount32: integer('latency_count_32').notNull(),
  latencyCount33: integer('latency_count_33').notNull(),
  latencyCount34: integer('latency_count_34').notNull(),
  latencyCount35: integer('latency_count_35').notNull(),
  latencyCount36: integer('latency_count_36').notNull(),
  latencyCount37: integer('latency_count_37').notNull(),
  latencyCount38: integer('latency_count_38').notNull(),
  latencyCount39: integer('latency_count_39').notNull(),
  latencyCount40: integer('latency_count_40').notNull(),
  latencyCount41: integer('latency_count_41').notNull(),
  latencyCount42: integer('latency_count_42').notNull(),
  latencyCount43: integer('latency_count_43').notNull(),
  latencyCount44: integer('latency_count_44').notNull(),
  latencyCount45: integer('latency_count_45').notNull(),
  latencyCount46: integer('latency_count_46').notNull(),
  latencyCount47: integer('latency_count_47').notNull(),
  latencyCount48: integer('latency_count_48').notNull(),
  latencyCount49: integer('latency_count_49').notNull(),

  // END
});

🙁 Actual behavior

Slow (2-3 second) TS validation time. This interferes with code-completion and makes for a bad DX.

🙂 Expected behavior

Type validation should stay performant.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginnen Sie mit der verknüpften StackBlitz-Reproduktion und vergleichen Sie die Validierungslatenz, während Sie zwischen den Feldern delayCount/latencyCount umschalten und 2 in "2" ändern. Lesen Sie die für die Eingrenzung der Verzögerung erforderlichen Einstiegspunkte für die TypeScript-Typprüfung und die Performance-Untersuchung. Die Aufgabe ist abgeschlossen, wenn die gemeldete Verlangsamung der Validierung behoben oder ihre Einschränkung mit unterstützender Regressionstestabdeckung klar charakterisiert ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers, developer-experience, performance
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.