microsoft / microsoft/TypeScript
Brittle circularity inherited from factory-produced class
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 1g 19h
- PR unite (30g)
- 117
Descrizione
TypeScript Version: 3.8.3
Search Terms: extend, from, circular, constructor, class, factory
The following works like a charm. I'm able to define a circular relationship between RecordShape and ArrayShape. This is wonderful!
class ArrayShape {
constructor(public of: any) { }
}
namespace ArrayShape {
export function of(of: any) {
return class extends ArrayShape {
constructor() {
super(of);
}
}
}
}
class RecordShape {
constructor(public of: object) { }
}
namespace RecordShape {
export function of(of: any) {
return class extends RecordShape {
constructor() {
super(of);
}
}
}
}
class CycleNodeA extends RecordShape.of(() => CycleNodeB) {}
class CycleNodeB extends ArrayShape.of(() => CycleNodeA) {}
However, this starts to break down as I make it more generic. In the example below, I begin to narrow down the type passed into the ArrayShape and RecordShape constructors. The result is––once again––circularity errors :/ here is the playground.
function TypeOnly<T>() {
return (undefined as any) as T;
}
// the base from which `ArrayShape` and `RecordShape` extend
abstract class Shape<N extends string, T> {
abstract readonly name: N;
abstract readonly type: T;
}
// extracts the `T` from a given shape
type DecodeShape<S extends Shape<string, any>> =
S extends Shape<string, infer T>
? T
: never;
// for referencing shapes which aren't yet defined
type PointerShape = (() => Shape<string, any>);
// utils for treating shape and pointer shape types as if they are the same
type ShapeLike = Shape<string, any> | PointerShape;
type NormalizeShape<S extends ShapeLike> =
S extends PointerShape
? S extends (() => infer SS) ? SS : never
: S;
type DecodeShapeLike<S extends ShapeLike> = DecodeShape<NormalizeShape<S>>;
class ArrayShape<T extends ShapeLike> extends Shape<"array", DecodeShapeLike<T>[]> {
readonly name = "array";
readonly type = TypeOnly<DecodeShapeLike<T>[]>();
constructor(public elementShape: T) {
super()
}
}
namespace ArrayShape {
export function of<T extends ShapeLike>(elementShape: T) {
return class extends ArrayShape<T> {
constructor() {
super(elementShape);
}
}
}
}
class RecordShape<T extends Record<string, ShapeLike>> extends Shape<"record", {
[K in keyof T]: DecodeShapeLike<T[K]>;
}> {
readonly name = "record";
readonly type = TypeOnly<{
[K in keyof T]: DecodeShapeLike<T[K]>;
}>();
constructor(public fieldShapes: T) {
super();
}
}
namespace RecordShape {
export function of<T extends Record<string, ShapeLike>>(fieldShapes: T) {
return class extends RecordShape<T> {
constructor() {
super(fieldShapes);
}
}
}
}
const CycleNodeA = RecordShape.of({
b: () => new CycleNodeB()
}) {}
class CycleNodeB extends ArrayShape.of(() => new CycleNodeA()) {}
If the circularity error turns out to be the intended behavior, apologies––I can post on StackOverflow instead. Otherwise, any help would be greatly appreciated! Thank you!
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Riproduci entrambi gli esempi collegati di TypeScript Playground con TypeScript 3.8.3, confrontando l’esempio circolare funzionante con la versione generica che segnala errori di circolarità. Inizia analizzando come il verificatore dei tipi gestisce i tipi ricorsivi tramite classi prodotte da factory e tipi condizionali o mappati. Il lavoro è completo quando viene determinato se la diagnosi è intenzionale e, in caso contrario, il comportamento segnalato viene coperto da un test di regressione e corretto.
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
- 25/100