microsoft / microsoft/TypeScript

Misleading error for a generic parameter with a default involving `this`

Aperta
#61,812 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: This-Typing Help Wanted Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

### 🔎 Search Terms

generic type parameter default, assignability, this

### 🕗 Version & Regression Information

- This changed in a9ad94ab3c35615b344c51e721f77655c225b524

### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.3#code/KYDwDg9gTgLgBAbwL4G4BQaAmwDGAbAQymDnwIGdy4ARCHAVwFtgA7GAHloebYDkDmAPkRo4cFgOAAuGnSasY-ZujHkAliwDmeYDAgtyMmAAs15dEgwaYwKADMCOEgEEWATy7y2I1Ru279QzgTMwsMbDJiUkJKOABRRgAjYExsTABhCDwdHBg1fWpgPBgCADE1Isx2UXidHhhyyoAVNzBgABoagHkAawBGOFAbFkwqT3r2AndhAF5a4HrGvEwWtsGQYdG4Kbc4AH5ZbgV2OLqFJZXW4GEZFmAAN1tOsV6AJnXNqlcPOXq4OfGx1OC3OFWWq2uzzgACEoBAeqwPqwtt9Ad45sDFmDLmshsiqDt9ocvBxMaDmlcbuIHrYagB6OlwCFwADkZLYF2ZeJGBPcRLRpLOHOxEKpd0eUBZcEwEGAVBYEHg5AIeXIdl2JhIOECMCgBGsrNRvwULIAdPTGcyWQKTkKGiLKVKzOJFdtKGpNBJEjpghBgldDe4BWaLWIxBCqBA7HAwHC2rBdiz1FodHoDFKiCQNNrGGAVWpvcBzWIGWGw1abez7RS2oInfLXRR1J6CIXff61my7ZyA9ytoSDpXuw7a3BbjTJebhMggA

### 💻 Code

Here's what essentially was trying to be written in an understandable way:

```ts
type Validator = (data: unknown) => ValidationResult;

interface Cloneable {
data: unknown;
clone(): this;
}

class ValidationResult implements Cloneable {
constructor(public data: T) {
this.isValid = true; // Actual validation logic left off.
}

clone(): this {
return structuredClone(this);
}

isValid: boolean;
}

class Collection> {
// Type 'ReturnType' does not satisfy the constraint 'Cloneable'.
// Type 'ValidationResult' is not assignable to type 'Cloneable'.
// The types returned by 'clone()' are incompatible between these types.
// Type 'ValidationResult' is not assignable to type 'ReturnType'.
constructor(validator: V, items: unknown[]) { } // Actual validation logic left off.

items: C[] = [];
}
```

Here's the a more distilled way of testing interesting cases:
```ts
export {};

declare class Document {
name: DocumentName;
singletons: this;
}

interface AnyDocument {
singletons: this;
}

declare class EmbeddedCollectionDeltaField<
ElementFieldType,
Ok1 extends Document = ElementFieldType extends any ? Document : never,
Ok2 extends AnyDocument = Document,
Broken extends AnyDocument = ElementFieldType extends any ? Document : never
// Type 'ElementFieldType extends any ? Document : never' does not satisfy the constraint 'AnyDocument'.
// Type 'Document' is not assignable to type 'AnyDocument'.
// Types of property 'singletons' are incompatible.
// Type 'Document' is not assignable to type 'ElementFieldType extends any ? Document : never'.
> {}
```

Finally this [playground](https://www.typescriptlang.org/play/#code/KYDwDg9gTgLgBAbwL4G4BQaCWA7GwoBmAhgMbBwDCE2BmA5gK5TAAmAIhCQwLbC4CS2AM4wi2MojRw4AQRYA3PjCbAAXHA5deuADwAiOYtwq9APnTSKRKCyHrNPJfqs2hZ9EgwwAnmHIAVX3IAXjgDBSUTOAAfMJdbPXQ0FmASABtrcnSiISENTkddB20YADkiXgAaOAAFTNw4ULFvU0lpAH0hCCYydWaLOCEcOjTgGGo7fK0nZuqYAAtMIXMMaWwKtSnCso2BsHqYdTrmXA8MFOzmOGzc2WxvYqU4UDxsWy2SnVm4ZtaEKTgnW6UF6P3uKDgAHpIZQINwSnAFks4N14GIWIj5uQlkIGOQ6BBgHkiAB3IjeNCeZKpDJXG55ACi3AARqwUiwqGlRiQYJhqGxgGlRAAxTCClg6AEM0YlUXiwJ+Z4gV7vBXASoAwSYXlENKYABerCVKryMnujwaoSoNHoKnYBRKghEYjIAG1pcBZWK0iw1QBdNB-KlAA) has the most confusing error.

### 🙁 Actual behavior

Multiple errors.

### 🙂 Expected behavior

No error. Or at least a less misleading error message. Specifically the lines `Type 'ValidationResult' is not assignable to type 'Cloneable'.` and `Type 'Document' is not assignable to type 'AnyDocument'.` are both testably false.

### Additional information about the issue

The reason for this misleading error appears to be this snippet:
```ts
if (constraintType && defaultType) {
checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
```

While the types are displayed as `defaultType` being assignable to `constraintType` it's really checking if `defaultType` is assignable to `getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType)`.

Specifically `this` is being substituted with the `defaultType` and the misleading errors about that ensues where it suddenly switches from talking about `Document` (a part of `defaultType`) being compared to `AnyDocument` (the `constraintType`) to talking comparing `Document` to the `defaultType` because `this = defaultType`. This is confusing because you don't normally expect to see the `defaultType` being compared to a part of the `defaultType`.

I admittedly don't understand the rationale for this specific substitution very well but I find it a bit surprising `this` is substituted with `defaultType` instead of `constratintType`. Regardless of what fix would be necessary to make this work, I can't deduce a way to cause unsoundness if this generic parameter default would be accepted.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con il controllo del vincolo/valore predefinito intorno a checkTypeAssignableTo e alla chiamata a getTypeWithThisArgument mostrata nell’issue. Riproduci i casi di Playground collegati e confronta le diagnosi riportate per gli esempi generici ridotti. È completato quando i valori predefiniti validi non producono più errori oppure le diagnosi descrivono accuratamente l’effettivo problema di assegnabilità.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.