@@ -1574,6 +1574,10 @@ namespace ts {
1574
1574
}
1575
1575
1576
1576
function symbolIsValue(symbol: Symbol): boolean {
1577
+ if (symbol.partialSource) {
1578
+ return symbolIsValue(symbol.partialSource);
1579
+ }
1580
+
1577
1581
// If it is an instantiated symbol, then it is a value if the symbol it is an
1578
1582
// instantiation of is a value.
1579
1583
if (symbol.flags & SymbolFlags.Instantiated) {
@@ -1629,6 +1633,12 @@ namespace ts {
1629
1633
return type;
1630
1634
}
1631
1635
1636
+ function createPartialTypeFromObjectType(target: Type): Type {
1637
+ const type = <PartialType>createType(TypeFlags.Partial | TypeFlags.ObjectType);
1638
+ type.type = target;
1639
+ return type;
1640
+ }
1641
+
1632
1642
// A reserved member name starts with two underscores, but the third character cannot be an underscore
1633
1643
// or the @ symbol. A third underscore indicates an escaped form of an identifer that started
1634
1644
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
@@ -2216,6 +2226,10 @@ namespace ts {
2216
2226
}
2217
2227
writer.writeKeyword("this");
2218
2228
}
2229
+ else if (type.flags & TypeFlags.Partial) {
2230
+ writer.writeKeyword("partial ");
2231
+ writeType((type as PartialType).type, flags);
2232
+ }
2219
2233
else if (getObjectFlags(type) & ObjectFlags.Reference) {
2220
2234
writeTypeReference(<TypeReference>type, nextFlags);
2221
2235
}
@@ -2787,6 +2801,7 @@ namespace ts {
2787
2801
case SyntaxKind.UnionType:
2788
2802
case SyntaxKind.IntersectionType:
2789
2803
case SyntaxKind.ParenthesizedType:
2804
+ case SyntaxKind.PartialType:
2790
2805
return isDeclarationVisible(<Declaration>node.parent);
2791
2806
2792
2807
// Default binding, import specifier and namespace import is visible
@@ -3530,7 +3545,24 @@ namespace ts {
3530
3545
return links.type;
3531
3546
}
3532
3547
3548
+ function getTypeOfPartialPropertySymbol(symbol: Symbol): Type {
3549
+ const links = getSymbolLinks(symbol);
3550
+ if (!links.type) {
3551
+ const type = getTypeOfSymbol(symbol.partialSource);
3552
+ if (strictNullChecks) {
3553
+ links.type = getUnionType([type, undefinedType]);
3554
+ }
3555
+ else {
3556
+ links.type = type;
3557
+ }
3558
+ }
3559
+ return links.type;
3560
+ }
3561
+
3533
3562
function getTypeOfSymbol(symbol: Symbol): Type {
3563
+ if (symbol.partialSource) {
3564
+ return getTypeOfPartialPropertySymbol(symbol);
3565
+ }
3534
3566
if (symbol.flags & SymbolFlags.Instantiated) {
3535
3567
return getTypeOfInstantiatedSymbol(symbol);
3536
3568
}
@@ -4187,6 +4219,29 @@ namespace ts {
4187
4219
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
4188
4220
}
4189
4221
4222
+ function resolvePartialTypeMembers(type: PartialType) {
4223
+ const source = getPropertiesOfType(type.type);
4224
+ const members = createMap<Symbol>();
4225
+ for (const member of source) {
4226
+ if (member.flags & SymbolFlags.Optional) {
4227
+ members[member.name] = member;
4228
+ }
4229
+ else {
4230
+ const synthetic = createSymbol(member.flags | SymbolFlags.SyntheticProperty | SymbolFlags.Optional, member.name);
4231
+ getSymbolLinks(synthetic).originalType = type.type;
4232
+ synthetic.partialSource = member;
4233
+ members[member.name] = synthetic;
4234
+ }
4235
+ }
4236
+ const stringIndex = getIndexInfoOfType(type.type, IndexKind.String);
4237
+ const numberIndex = getIndexInfoOfType(type.type, IndexKind.Number);
4238
+ const stringIndexType = stringIndex && (strictNullChecks ? getUnionType([stringIndex.type, undefinedType]) : stringIndex.type);
4239
+ const numberIndexType = numberIndex && (strictNullChecks ? getUnionType([numberIndex.type, undefinedType]) : numberIndex.type);
4240
+ setObjectTypeMembers(type, members, emptyArray, emptyArray,
4241
+ stringIndex && createIndexInfo(stringIndexType, stringIndex.isReadonly, stringIndex.declaration),
4242
+ numberIndex && createIndexInfo(numberIndexType, numberIndex.isReadonly, numberIndex.declaration));
4243
+ }
4244
+
4190
4245
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
4191
4246
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature {
4192
4247
const sig = new Signature(checker);
@@ -4407,6 +4462,8 @@ namespace ts {
4407
4462
}
4408
4463
else if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
4409
4464
resolveAnonymousTypeMembers(<AnonymousType>type);
4465
+ } else if ((<ObjectType>type).objectFlags & ObjectFlags.Partial) {
4466
+ resolvePartialTypeMembers(<PartialType>type);
4410
4467
}
4411
4468
}
4412
4469
else if (type.flags & TypeFlags.Union) {
@@ -5692,6 +5749,40 @@ namespace ts {
5692
5749
return links.resolvedType;
5693
5750
}
5694
5751
5752
+ function getTypeFromPartialTypeNode(node: PartialTypeNode): Type {
5753
+ const links = getNodeLinks(node);
5754
+ if (!links.resolvedType) {
5755
+ links.resolvedType = getPartialType(getTypeOfNode(node.type));
5756
+ }
5757
+ return links.resolvedType;
5758
+ }
5759
+
5760
+ function getPartialType(type: Type): Type {
5761
+ if (type.resolvedPartialType) {
5762
+ return type.resolvedPartialType;
5763
+ }
5764
+
5765
+ if (type.flags & TypeFlags.Partial) {
5766
+ // partial partial T === partial T
5767
+ return type;
5768
+ }
5769
+ if (type.flags & TypeFlags.Union) {
5770
+ return type.resolvedPartialType = getUnionType((type as UnionType).types.map(getPartialType));
5771
+ }
5772
+ if (type.flags & TypeFlags.Intersection) {
5773
+ return type.resolvedPartialType = getIntersectionType((type as IntersectionType).types.map(getPartialType));
5774
+ }
5775
+ if (type.flags & TypeFlags.ObjectType) {
5776
+ return type.resolvedPartialType = createPartialTypeFromObjectType(type);
5777
+ }
5778
+
5779
+ // Type parameter
5780
+ Debug.assert(!!(type.flags & TypeFlags.TypeParameter));
5781
+ const result = <PartialType>createType(TypeFlags.Partial);
5782
+ result.type = type;
5783
+ return type.resolvedPartialType = result;
5784
+ }
5785
+
5695
5786
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
5696
5787
const links = getNodeLinks(node);
5697
5788
if (!links.resolvedType) {
@@ -5841,6 +5932,8 @@ namespace ts {
5841
5932
return getTypeFromUnionTypeNode(<UnionTypeNode>node, aliasSymbol, aliasTypeArguments);
5842
5933
case SyntaxKind.IntersectionType:
5843
5934
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node, aliasSymbol, aliasTypeArguments);
5935
+ case SyntaxKind.PartialType:
5936
+ return getTypeFromPartialTypeNode(<PartialTypeNode>node);
5844
5937
case SyntaxKind.ParenthesizedType:
5845
5938
case SyntaxKind.JSDocNullableType:
5846
5939
case SyntaxKind.JSDocNonNullableType:
@@ -6120,6 +6213,9 @@ namespace ts {
6120
6213
if (type.flags & TypeFlags.Intersection) {
6121
6214
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
6122
6215
}
6216
+ if (type.flags & TypeFlags.Partial) {
6217
+ return getPartialType(instantiateType((<PartialType>type).type, mapper));
6218
+ }
6123
6219
}
6124
6220
return type;
6125
6221
}
@@ -6603,6 +6699,17 @@ namespace ts {
6603
6699
6604
6700
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
6605
6701
6702
+ // If the target is a 'partial T', the only allowed source is T, partial T, or {}
6703
+ if ((target.flags & (TypeFlags.Partial | TypeFlags.ObjectType)) === TypeFlags.Partial) {
6704
+ if ((source === emptyObjectType) || ((<PartialType>target).type === source)) {
6705
+ return Ternary.True;
6706
+ }
6707
+ if (reportErrors) {
6708
+ reportRelationError(headMessage, source, target);
6709
+ }
6710
+ return Ternary.False;
6711
+ }
6712
+
6606
6713
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
6607
6714
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
6608
6715
if (reportErrors) {
@@ -15021,6 +15128,10 @@ namespace ts {
15021
15128
forEach(node.types, checkSourceElement);
15022
15129
}
15023
15130
15131
+ function checkPartialType(node: PartialTypeNode) {
15132
+ checkSourceElement(node.type);
15133
+ }
15134
+
15024
15135
function isPrivateWithinAmbient(node: Node): boolean {
15025
15136
return (getModifierFlags(node) & ModifierFlags.Private) && isInAmbientContext(node);
15026
15137
}
@@ -18287,6 +18398,8 @@ namespace ts {
18287
18398
case SyntaxKind.UnionType:
18288
18399
case SyntaxKind.IntersectionType:
18289
18400
return checkUnionOrIntersectionType(<UnionOrIntersectionTypeNode>node);
18401
+ case SyntaxKind.PartialType:
18402
+ return checkPartialType(<PartialTypeNode>node);
18290
18403
case SyntaxKind.ParenthesizedType:
18291
18404
return checkSourceElement((<ParenthesizedTypeNode>node).type);
18292
18405
case SyntaxKind.FunctionDeclaration:
@@ -18639,7 +18752,7 @@ namespace ts {
18639
18752
node = node.parent;
18640
18753
}
18641
18754
18642
- return node.parent && (node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.JSDocTypeReference) ;
18755
+ return node.parent && (node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.JSDocTypeReference);
18643
18756
}
18644
18757
18645
18758
function isHeritageClauseElementIdentifier(entityName: Node): boolean {
@@ -19031,15 +19144,23 @@ namespace ts {
19031
19144
19032
19145
function getRootSymbols(symbol: Symbol): Symbol[] {
19033
19146
if (symbol.flags & SymbolFlags.SyntheticProperty) {
19034
- const symbols: Symbol[] = [];
19035
- const name = symbol.name;
19036
- forEach(getSymbolLinks(symbol).containingType.types, t => {
19037
- const symbol = getPropertyOfType(t, name);
19038
- if (symbol) {
19039
- symbols.push(symbol);
19040
- }
19041
- });
19042
- return symbols;
19147
+ const links = getSymbolLinks(symbol);
19148
+ if (links.containingType) {
19149
+ const symbols: Symbol[] = [];
19150
+ const name = symbol.name;
19151
+
19152
+ forEach(links.containingType.types, t => {
19153
+ const symbol = getPropertyOfType(t, name);
19154
+ if (symbol) {
19155
+ symbols.push(symbol);
19156
+ }
19157
+ });
19158
+ return symbols;
19159
+ }
19160
+ else if (links.originalType) {
19161
+ return [links.originalType.symbol];
19162
+ }
19163
+ return emptyArray;
19043
19164
}
19044
19165
else if (symbol.flags & SymbolFlags.Transient) {
19045
19166
let target: Symbol;
0 commit comments