Skip to content

Commit

Permalink
Improve relationship check for mapped type sources under `exactOption…
Browse files Browse the repository at this point in the history
…alPropertyTypes`
  • Loading branch information
Andarist committed Dec 31, 2024
1 parent 56a0825 commit 2f33b46
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 7 deletions.
23 changes: 21 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12337,7 +12337,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function getNonMissingTypeOfSymbol(symbol: Symbol) {
return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
let type = getTypeOfSymbol(symbol);
if (exactOptionalPropertyTypes) {
const checkFlags = getCheckFlags(symbol);
if (checkFlags & CheckFlags.Mapped) {
const mappedType = (symbol as MappedSymbol).links.mappedType;
const keyType = (symbol as MappedSymbol).links.keyType;
const modifiersType = getModifiersTypeFromMappedType(mappedType);
if (modifiersType !== unknownType) {
type = mapType(type, t => {
if (!(t.flags & TypeFlags.IndexedAccess) || (t as IndexedAccessType).objectType !== modifiersType || (t as IndexedAccessType).indexType !== keyType) {
return t;
}
return getIndexedAccessType(modifiersType, keyType, AccessFlags.NonMissing, /*accessNode*/ undefined, t.aliasSymbol, t.aliasTypeArguments);
});
}
}
}
return removeMissingType(type, !!(symbol.flags & SymbolFlags.Optional));
}

function isReferenceToSomeType(type: Type, targets: readonly Type[]) {
Expand Down Expand Up @@ -18630,7 +18647,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return autoType;
}
}
const propType = accessFlags & AccessFlags.Writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
const propType = accessFlags & AccessFlags.Writing ?
getWriteTypeOfSymbol(prop) :
removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional && accessFlags & AccessFlags.NonMissing));
return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? getFlowTypeOfReference(accessExpression, propType) :
accessNode && isIndexedAccessTypeNode(accessNode) && containsMissingType(propType) ? getUnionType([propType, undefinedType]) :
propType;
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6835,11 +6835,12 @@ export const enum AccessFlags {
Writing = 1 << 2,
CacheSymbol = 1 << 3,
AllowMissing = 1 << 4,
ExpressionPosition = 1 << 5,
ReportDeprecated = 1 << 6,
SuppressNoImplicitAnyError = 1 << 7,
Contextual = 1 << 8,
Persistent = IncludeUndefined,
NonMissing = 1 << 5,
ExpressionPosition = 1 << 6,
ReportDeprecated = 1 << 7,
SuppressNoImplicitAnyError = 1 << 8,
Contextual = 1 << 9,
Persistent = IncludeUndefined | NonMissing,
}

// Indexed access types (TypeFlags.IndexedAccess)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//// [tests/cases/compiler/mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts] ////

=== mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts ===
// https://github.com/microsoft/TypeScript/issues/60233

type T = {
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))

foo?: true;
>foo : Symbol(foo, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 2, 10))

bar?: true;
>bar : Symbol(bar, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 3, 13))

};

type WrappedT<t extends T> = [t];
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 14))
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 14))

type OmitBarFromWrapped<t> = t extends WrappedT<infer inner>
>OmitBarFromWrapped : Symbol(OmitBarFromWrapped, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 7, 33))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 24))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 24))
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 53))

? WrappedT<Omit<inner, "bar">>
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 9, 53))

: never;

type OmitHomomorphicFromWrapped<t> = t extends WrappedT<infer inner>
>OmitHomomorphicFromWrapped : Symbol(OmitHomomorphicFromWrapped, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 11, 10))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 32))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 32))
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 61))

? WrappedT<HomomorphicOmit<inner, "bar">>
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 13, 61))

: never;

type HomomorphicOmit<t, keyToOmit> = {
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
>keyToOmit : Symbol(keyToOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 23))

[k in keyof t as k extends keyToOmit ? never : k]: t[k];
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
>keyToOmit : Symbol(keyToOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 23))
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 17, 21))
>k : Symbol(k, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 18, 3))

};

type OmitHomomorphicFromWrappedConformed<t> = t extends WrappedT<infer inner>
>OmitHomomorphicFromWrappedConformed : Symbol(OmitHomomorphicFromWrappedConformed, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 19, 2))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 41))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 41))
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 70))

? WrappedT<conform<HomomorphicOmit<inner, "bar">, T>>
>WrappedT : Symbol(WrappedT, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 5, 2))
>conform : Symbol(conform, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 23, 10))
>HomomorphicOmit : Symbol(HomomorphicOmit, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 15, 10))
>inner : Symbol(inner, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 21, 70))
>T : Symbol(T, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 0, 0))

: never;

type conform<t, base> = t extends base ? t : base;
>conform : Symbol(conform, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 23, 10))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))
>t : Symbol(t, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 13))
>base : Symbol(base, Decl(mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts, 25, 15))

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//// [tests/cases/compiler/mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts] ////

=== mappedTypeConstraintAssignabilityExactOptionalPropertyTypes1.ts ===
// https://github.com/microsoft/TypeScript/issues/60233

type T = {
>T : T
> : ^

foo?: true;
>foo : true | undefined
> : ^^^^^^^^^^^^^^^^
>true : true
> : ^^^^

bar?: true;
>bar : true | undefined
> : ^^^^^^^^^^^^^^^^
>true : true
> : ^^^^

};

type WrappedT<t extends T> = [t];
>WrappedT : WrappedT<t>
> : ^^^^^^^^^^^

type OmitBarFromWrapped<t> = t extends WrappedT<infer inner>
>OmitBarFromWrapped : OmitBarFromWrapped<t>
> : ^^^^^^^^^^^^^^^^^^^^^

? WrappedT<Omit<inner, "bar">>
: never;

type OmitHomomorphicFromWrapped<t> = t extends WrappedT<infer inner>
>OmitHomomorphicFromWrapped : OmitHomomorphicFromWrapped<t>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

? WrappedT<HomomorphicOmit<inner, "bar">>
: never;

type HomomorphicOmit<t, keyToOmit> = {
>HomomorphicOmit : HomomorphicOmit<t, keyToOmit>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[k in keyof t as k extends keyToOmit ? never : k]: t[k];
};

type OmitHomomorphicFromWrappedConformed<t> = t extends WrappedT<infer inner>
>OmitHomomorphicFromWrappedConformed : OmitHomomorphicFromWrappedConformed<t>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

? WrappedT<conform<HomomorphicOmit<inner, "bar">, T>>
: never;

type conform<t, base> = t extends base ? t : base;
>conform : conform<t, base>
> : ^^^^^^^^^^^^^^^^

0 comments on commit 2f33b46

Please sign in to comment.