-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Add optionality to mapped type substitutions based on existence of an optional modifiers prop #57493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add optionality to mapped type substitutions based on existence of an optional modifiers prop #57493
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18514,10 +18514,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { | |
return !!(getUnionType([intersectTypes(type1, type2), neverType]).flags & TypeFlags.Never); | ||
} | ||
|
||
function hasOptionalModifiersProperty(mappedType: MappedType) { | ||
const modifiersType = getApparentType(getModifiersTypeFromMappedType(mappedType)); | ||
if (!(modifiersType.flags & TypeFlags.Object)) { | ||
return false; | ||
} | ||
const properties = resolveStructuredTypeMembers(modifiersType as ObjectType).properties; | ||
return some(properties, p => !!(p.flags & SymbolFlags.Optional)); | ||
} | ||
|
||
function substituteIndexedMappedType(objectType: MappedType, index: Type) { | ||
const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]); | ||
const templateMapper = combineTypeMappers(objectType.mapper, mapper); | ||
return instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper); | ||
const type = instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper); | ||
return addOptionality(type, /*isProperty*/ true, hasOptionalModifiersProperty(objectType)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: this should get the list of known optional properties and check if |
||
} | ||
|
||
function getIndexedAccessType(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,9 +31,10 @@ keyofAndIndexedAccess2.ts(68,3): error TS2322: Type 'number' is not assignable t | |
'number' is assignable to the constraint of type 'T[K]', but 'T[K]' could be instantiated with a different subtype of constraint 'number'. | ||
keyofAndIndexedAccess2.ts(108,5): error TS2322: Type '123' is not assignable to type 'Type[K]'. | ||
Type 'number' is not assignable to type 'never'. | ||
keyofAndIndexedAccess2.ts(115,21): error TS2313: Type parameter 'Q' has a circular constraint. | ||
|
||
|
||
==== keyofAndIndexedAccess2.ts (23 errors) ==== | ||
==== keyofAndIndexedAccess2.ts (24 errors) ==== | ||
function f1(obj: { a: number, b: 0 | 1, c: string }, k0: 'a', k1: 'a' | 'b', k2: 'a' | 'b' | 'c') { | ||
obj[k0] = 1; | ||
obj[k0] = 2; | ||
|
@@ -205,6 +206,9 @@ keyofAndIndexedAccess2.ts(108,5): error TS2322: Type '123' is not assignable to | |
type StrictExtract<T, U> = T extends U ? U extends T ? T : never : never; | ||
type StrictExclude<T, U> = T extends StrictExtract<T, U> ? never : T; | ||
type A<T> = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what's the best strategy to avoid circularity here. I didn't look into it yet. I'm hitting the 🛌 but maybe somebody would chime in with some suggestions in the meantime ;p |
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
!!! error TS2313: Type parameter 'Q' has a circular constraint. | ||
!!! related TS2751 keyofAndIndexedAccess2.ts:116:36: Circularity originates in type at this location. | ||
type B<T, V> = A<{ [Q in keyof T]: StrictExclude<B<T[Q], V>, {}>; }>; | ||
|
||
// Repros from #30938 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: might also have to handle intersection (that's what
isWeakType
is doing) and I need to recheck behavior with unionsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recheck behavior with union types later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mateusnasciment Please try to keep comments actionable and on-topic