microsoft / microsoft/TypeScript

Regression: Type T[K] as an array when sliced loses its type

Offen
#31,549 3 Kommentare 3 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bug Domain: Indexed Access Types Needs Human Review
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

TypeScript Version: 3.4.5

Search Terms:
array property generics
Code

export function GetArrayProp<U, K extends string, T extends Record<K, U[]>>(
  state: T,
  prop: K,
) {
  //good
  let x1: T[K] = state[prop];
  //good
  let x2: U[] = state[prop];
  //good
  let x3: U[] = state[prop].slice(0);
  //error
  let x4: T[K] = state[prop].slice(0);
}

While you can argue that U[] isn't necessarily assignable to type T[K]. Look at the following code.
It's hard to see how TypeFromArray<T[K]>[]'s type should be any different than T[K]

export type TypeFromArray<T> = T extends (infer R)[] ? R : never;

export function GetArrayProp<K extends string, T extends Record<K, Array<TypeFromArray<T[K]>>>>(
  obj: T,
  prop: K,
) {
  //good
  let x1: T[K] = obj[prop];
  //good
  let x2 = obj[prop].slice(0);
  //error Type 'TypeFromArray<T[K]>[]' is not assignable to type 'T[K]'.
  let x3: T[K] = obj[prop].slice(0);
}

Expected behavior:

No errors.
T[K] and U[] should be assignable to each other.
state[prop].slice(0) should be of the same type as state[prop]
TypeFromArray<T[K]>[]'s type should be not be any different than T[K]

This code works in version 3.2.4 but stopped working in 3.3.1

Actual behavior:

Error Type 'U[]' is not assignable to type 'T[K]'.
Error Type 'TypeFromArray<T[K]>[]' is not assignable to type 'T[K]'

Playground Link:

Playground Link

My main goal is to be able to pluck array properties and modify the arrays without losing the type T[K]
The code above is simplified to show how TS is behaving.
See my use case below.

It's hard to see how TypeFromArray<T[K]>[]'s type should be any different than T[K]
The code below used to work when using 3.2.4


import { EntityState, EntityAdapter } from '@ngrx/entity';
import { Action } from '@ngrx/store';

export type TypeFromArray<T> = T extends (infer R)[] ? R : never;

type Selector<T> = (s: T) => boolean;


function ModifyEntityFromState<T>(entityId: number, state: EntityState<T>, callBack:  (acnt: T) => void): T {
  const t = state.entities[entityId];
  const acnt = JSON.parse(JSON.stringify(t)) as T;
  callBack(acnt);
  return acnt;
}


export function ModifyPropertyFromState<T, K extends keyof T>(
  entityId: number,
  state: EntityState<T>,
  prop: K,
  callBack: (a: T[K]) => T[K],
): T {
  return ModifyEntityFromState( entityId, state, (acnt) => {
    acnt[prop] = callBack( acnt[prop]  );
  });
}


export function EditArrayFromState<
T extends Record<K, Array<TypeFromArray<T[K]>>>,
K extends keyof T,
U extends TypeFromArray<T[K]>
>(
  entityId: number, state: EntityState<T>, prop: K,
  selector: Selector<U>,
  modified: U
): T {
  return ModifyPropertyFromState( entityId, state, prop, (a) => {
//Argument of type '(a: T[K]) => TypeFromArray<T[K]>[]' is not assignable to parameter of type '(a: T[K]) => T[K]'.
//  Type 'TypeFromArray<T[K]>[]' is not assignable to type 'T[K]'
    const idx = a.findIndex(selector);
    return  [
      ...a.slice(0, idx),
      ...a.slice(idx + 1),
      modified
    ];
  });
}



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

Reproduziere das Problem mit den bereitgestellten TypeScript-Snippets und dem Playground-Link und vergleiche dabei das Verhalten in 3.2.4, 3.3.1 und 3.4.5. Verfolge die Typprüfung für generische Indexed-Access- und Array-Slice-Typen, füge dann einen Regressionstest hinzu, der zeigt, dass der geslicte Wert weiterhin T[K] zuweisbar ist, und überprüfe die Testsuite.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
52/100

Neue Issues direkt in Ihr Postfach

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