microsoft / microsoft/TypeScript

Strange behavior of types while using nested mapped types and generics

Aperta
#54,775 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Needs Investigation
Lingua principale
Go
Stelle
111k
Fork
14.4k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

Bug Report

I got two differents typings while nesting objects using some object-builder functions and generic optional typings, keeping it quite basic.

These two typings show up in a one-in-two pattern as we dig into the nested objects.
The second one matches with the type of the object-builder.

It can be a misuse of mine so let me know ...

🔎 Search Terms
  • mapped type
  • nested
  • partial optional
  • generic
🕗 Version & Regression Information

Typescript versions 5.1.4 & 5.2.0-dev.20230625 & 4.1.6

Just discovered it, so AFAIK this is not a regression.

⏯ Playground Link

Just here

💻 Code
type OptionalyProped<OPTL extends number> = { optlValue?: OPTL }
export const optionalyProped = <OPTL extends number>(proped: OptionalyProped<OPTL>): OptionalyProped<OPTL> => proped


type ObjectOfProped<T extends { [key: string]: ObjectOrProped }> = { structure: T }
export const objectOfProped = <OBJ extends { [key: string]: ObjectOrProped }>(
    objectOf: ObjectOfProped<OBJ>
    ): ObjectOfProped<OBJ> => objectOf

type ObjectOrProped = ObjectOfProped<any> | OptionalyProped<any>

const test = objectOfProped({
	structure: {
		n: optionalyProped({}),
                p: optionalyProped({ optlValue: 21}),
		o: objectOfProped({
			structure: {
				n: optionalyProped({}),
                                p: optionalyProped({ optlValue: 21}),
				o: objectOfProped({
					structure: {
						n: optionalyProped({}),
                                                p: optionalyProped({ optlValue: 21}),
						o: objectOfProped({
							structure: {
								n: optionalyProped({}),
                                                                p: optionalyProped({ optlValue: 21}),
							},
						}),
					},
				}),
			},
		}),
	},
})

const n = optionalyProped({ }) // typed: OptionalyProped<number>
const p = optionalyProped({ optlValue: 21 }) // typed: OptionalyProped<21>

🙁 Actual behavior
typeof test = ObjectOfProped<{
    n: OptionalyProped<any>;                // first behavior
    p: OptionalyProped<number>;
    o: ObjectOfProped<{
        n: OptionalyProped<number>;         // second behavior (legit one)
        p: OptionalyProped<21>;
        o: ObjectOfProped<{
            n: OptionalyProped<any>;
            p: OptionalyProped<number>;
            o: ObjectOfProped<{
                n: OptionalyProped<number>;
                p: OptionalyProped<21>;
            }>;
        }>;
    }>;
}>
🙂 Expected behavior
typeof test = ObjectOfProped<{
    n: OptionalyProped<number>;             // always
    p: OptionalyProped<21>;
    o: ObjectOfProped<{
        n: OptionalyProped<number>;         // the same
        p: OptionalyProped<21>;
        o: ObjectOfProped<{
            n: OptionalyProped<number>;     // type
            p: OptionalyProped<21>;
            o: ObjectOfProped<{
                n: OptionalyProped<number>;
                p: OptionalyProped<21>;
            }>;
        }>;
    }>;
}>

Thanks

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 link fornito a TypeScript Playground e con l'esempio di object-builder annidato, confrontando il tipo inferito di test con le dichiarazioni autonome di n e p. Traccia il modo in cui le chiamate generiche annidate inferiscono i tipi OptionalyProped; il lavoro è completato quando le proprietà n annidate inferiscono costantemente OptionalyProped<number> e le proprietà p mantengono OptionalyProped<21>.

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

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.