-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Mapped types #12114
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
Mapped types #12114
Changes from 1 commit
7cd39e3
d1a8af5
fc450a2
ecdb74c
7807ac9
1c7b397
507ab30
2564e1c
5de63a7
de93876
9f3aa38
8aef1e6
7ca5923
a562d6e
cf2953b
aca7e2f
3dd11e4
2170ff6
b81c226
de2da2c
aca1ab3
64d2698
cd185f2
1c7ec6b
364142c
e9b6ddc
ca3f797
5028a44
9ac7667
6ceab7b
cd05c07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2546,13 +2546,20 @@ namespace ts { | |
| writePunctuation(writer, SyntaxKind.OpenBraceToken); | ||
| writer.writeLine(); | ||
| writer.increaseIndent(); | ||
| if (type.isReadonly) { | ||
| writeKeyword(writer, SyntaxKind.ReadonlyKeyword); | ||
| writeSpace(writer); | ||
| } | ||
| writePunctuation(writer, SyntaxKind.OpenBracketToken); | ||
| appendSymbolNameOnly((type.target || type).typeParameter.symbol, writer); | ||
| appendSymbolNameOnly(type.typeParameter.symbol, writer); | ||
| writeSpace(writer); | ||
| writeKeyword(writer, SyntaxKind.InKeyword); | ||
| writeSpace(writer); | ||
| writeType(constraintType, TypeFormatFlags.None); | ||
| writePunctuation(writer, SyntaxKind.CloseBracketToken); | ||
| if (type.isOptional) { | ||
| writePunctuation(writer, SyntaxKind.QuestionToken); | ||
| } | ||
| writePunctuation(writer, SyntaxKind.ColonToken); | ||
| writeSpace(writer); | ||
| writeType(getTemplateTypeFromMappedType(type), TypeFormatFlags.None); | ||
|
|
@@ -4453,28 +4460,40 @@ namespace ts { | |
| const members: SymbolTable = createMap<Symbol>(); | ||
| let stringIndexInfo: IndexInfo; | ||
| let numberIndexInfo: IndexInfo; | ||
| const target = type.target || type; | ||
| const keyType = getApparentType(getConstraintTypeFromMappedType(type)); | ||
| const constraintType = getConstraintTypeFromMappedType(type); | ||
| const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentType(constraintType) : constraintType; | ||
| const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType; | ||
| forEachType(iterationType, t => { | ||
| const iterationMapper = createUnaryTypeMapper(target.typeParameter, t); | ||
| const iterationMapper = createUnaryTypeMapper(type.typeParameter, t); | ||
| const templateMapper = type.mapper ? combineTypeMappers(type.mapper, iterationMapper) : iterationMapper; | ||
| const propType = instantiateType(type.templateType, templateMapper); | ||
| if (t.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) { | ||
| const propName = (<LiteralType>t).text; | ||
| const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, propName); | ||
| prop.type = instantiateType(target.templateType, templateMapper); | ||
| const optionalFlag = type.isOptional ? SymbolFlags.Optional : 0; | ||
| const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | optionalFlag, propName); | ||
| prop.type = addOptionality(propType, type.isOptional); | ||
| prop.isReadonly = type.isReadonly; | ||
| members[propName] = prop; | ||
| } | ||
| else if (t.flags & TypeFlags.String) { | ||
| stringIndexInfo = createIndexInfo(propType, type.isReadonly); | ||
| } | ||
| else if (t.flags & TypeFlags.Number) { | ||
| numberIndexInfo = createIndexInfo(propType, type.isReadonly); | ||
| } | ||
| }); | ||
| if (stringIndexInfo && numberIndexInfo && isTypeIdenticalTo(stringIndexInfo.type, numberIndexInfo.type)) { | ||
| numberIndexInfo = undefined; | ||
| } | ||
| setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); | ||
| } | ||
|
|
||
| function getConstraintTypeFromMappedType(type: MappedType) { | ||
|
Member
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. jsdoc format
Member
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. Looks like
Member
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. Actually, it looks like
Member
Author
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. Fixed the comments. |
||
| return instantiateType(getConstraintOfTypeParameter((type.target || type).typeParameter), type.mapper || identityMapper); | ||
| return instantiateType(getConstraintOfTypeParameter(type.typeParameter), type.mapper || identityMapper); | ||
| } | ||
|
|
||
| function getTemplateTypeFromMappedType(type: MappedType) { | ||
| return instantiateType((type.target || type).templateType, type.mapper || identityMapper); | ||
| return instantiateType(type.templateType, type.mapper || identityMapper); | ||
| } | ||
|
|
||
| function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { | ||
|
|
@@ -5919,6 +5938,8 @@ namespace ts { | |
| const type = <MappedType>createObjectType(ObjectFlags.Mapped); | ||
| type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)); | ||
| type.templateType = node.type ? getTypeFromTypeNode(node.type) : anyType; | ||
| type.isReadonly = !!node.readonlyToken; | ||
| type.isOptional = !!node.questionToken; | ||
| type.aliasSymbol = aliasSymbol; | ||
| type.aliasTypeArguments = aliasTypeArguments; | ||
| links.resolvedType = type; | ||
|
|
@@ -6265,15 +6286,27 @@ namespace ts { | |
| return result; | ||
| } | ||
|
|
||
| function instantiateAnonymousOrMappedType(type: AnonymousType | MappedType, mapper: TypeMapper): ObjectType { | ||
| const result = <AnonymousType | MappedType>createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol); | ||
| function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType { | ||
| const result = <AnonymousType>createObjectType(ObjectFlags.Anonymous | ObjectFlags.Instantiated, type.symbol); | ||
| result.target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type; | ||
| result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper; | ||
| result.aliasSymbol = type.aliasSymbol; | ||
| result.aliasTypeArguments = mapper.targetTypes; | ||
| return result; | ||
| } | ||
|
|
||
| function instantiateMappedType(type: MappedType, mapper: TypeMapper): MappedType { | ||
| const result = <MappedType>createObjectType(ObjectFlags.Mapped | ObjectFlags.Instantiated, type.symbol); | ||
| result.typeParameter = type.typeParameter; | ||
| result.templateType = type.templateType; | ||
| result.isReadonly = type.isReadonly; | ||
| result.isOptional = type.isOptional; | ||
| result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper; | ||
| result.aliasSymbol = type.aliasSymbol; | ||
| result.aliasTypeArguments = mapper.targetTypes; | ||
| return result; | ||
| } | ||
|
|
||
| function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) { | ||
| if (!(symbol.declarations && symbol.declarations.length)) { | ||
| return false; | ||
|
|
@@ -6342,10 +6375,10 @@ namespace ts { | |
| return type.symbol && | ||
| type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && | ||
| ((<ObjectType>type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ? | ||
| instantiateCached(type, mapper, instantiateAnonymousOrMappedType) : type; | ||
| instantiateCached(type, mapper, instantiateAnonymousType) : type; | ||
| } | ||
| if ((<ObjectType>type).objectFlags & ObjectFlags.Mapped) { | ||
| return instantiateCached(type, mapper, instantiateAnonymousOrMappedType); | ||
| return instantiateCached(type, mapper, instantiateMappedType); | ||
| } | ||
| if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) { | ||
| return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType)); | ||
|
|
||
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.
can you put this next to mapType and filterType?
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.
Done.