Merge branch 'object-spread' into object-rest-syntax

This commit is contained in:
Nathan Shively-Sanders 2016-11-03 10:12:45 -07:00
commit 7ff8876096
30 changed files with 417 additions and 1412 deletions

View File

@ -113,7 +113,6 @@ namespace ts {
const tupleTypes: GenericType[] = [];
const unionTypes = createMap<UnionType>();
const intersectionTypes = createMap<IntersectionType>();
const spreadTypes = createMap<SpreadType>();
const stringLiteralTypes = createMap<LiteralType>();
const numericLiteralTypes = createMap<LiteralType>();
const evolvingArrayTypes: EvolvingArrayType[] = [];
@ -2244,9 +2243,6 @@ namespace ts {
else if (type.flags & TypeFlags.UnionOrIntersection) {
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
}
else if (type.flags & TypeFlags.Spread) {
writeSpreadType(type as SpreadType);
}
else if (getObjectFlags(type) & ObjectFlags.Anonymous) {
writeAnonymousType(<ObjectType>type, nextFlags);
}
@ -2362,48 +2358,6 @@ namespace ts {
}
}
function writeSpreadType(type: SpreadType) {
writePunctuation(writer, SyntaxKind.OpenBraceToken);
writer.writeLine();
writer.increaseIndent();
writeSpreadTypeWorker(type, /*atEnd*/true, type.symbol);
writer.decreaseIndent();
writePunctuation(writer, SyntaxKind.CloseBraceToken);
}
function writeSpreadTypeWorker(type: SpreadType, atEnd: boolean, container: Symbol): void {
if (type.left.flags & TypeFlags.Spread) {
writeSpreadTypeWorker(type.left as SpreadType, /*atEnd*/false, container);
}
else {
const saveInObjectTypeLiteral = inObjectTypeLiteral;
inObjectTypeLiteral = true;
writeObjectLiteralType(resolveStructuredTypeMembers(type.left as ResolvedType));
inObjectTypeLiteral = saveInObjectTypeLiteral;
}
if (type.right.symbol === container) {
// if type.right was written as part of the spread type, don't surround with ...{ }.
// this gives { a: number, ... T } instead of { ...{ a: number }, ...T }
const saveInObjectTypeLiteral = inObjectTypeLiteral;
inObjectTypeLiteral = true;
writeObjectLiteralType(resolveStructuredTypeMembers(type.right as ResolvedType));
inObjectTypeLiteral = saveInObjectTypeLiteral;
}
else {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
writeType(type.right, TypeFormatFlags.None);
if (atEnd) {
writeSpace(writer);
}
else {
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
}
}
function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
const symbol = type.symbol;
if (symbol) {
@ -3643,7 +3597,6 @@ namespace ts {
links.type = getUnionType([getTypeOfSymbol(links.leftSpread), getTypeOfSymbol(links.rightSpread)]);
}
return links.type;
}
function getTargetType(type: Type): Type {
@ -4587,18 +4540,13 @@ namespace ts {
return type.resolvedApparentType;
}
function getApparentTypeOfSpread(type: SpreadType) {
return getApparentType(type.right);
}
/**
* For a type parameter, return the base constraint of the type parameter. For the string, number,
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
let t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>type) : type;
t = t.flags & TypeFlags.Spread ? getApparentTypeOfSpread(type as SpreadType) : t;
const t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>type) : type;
return t.flags & TypeFlags.StringLike ? globalStringType :
t.flags & TypeFlags.NumberLike ? globalNumberType :
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
@ -4660,7 +4608,7 @@ namespace ts {
propTypes.push(type);
}
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name);
result.syntheticKind === SyntheticSymbolKind.UnionOrIntersection;
result.syntheticKind = SyntheticSymbolKind.UnionOrIntersection;
result.containingType = containingType;
result.hasNonUniformType = hasNonUniformType;
result.isPartial = isPartial;
@ -5937,12 +5885,6 @@ namespace ts {
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const hasSpread = (node.kind === SyntaxKind.TypeLiteral &&
find((node as TypeLiteralNode).members, elt => elt.kind === SyntaxKind.SpreadTypeElement));
if (hasSpread) {
return getTypeFromSpreadTypeLiteral(node, aliasSymbol, aliasTypeArguments);
}
// Deferred resolution of members is handled by resolveObjectTypeMembers
if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) {
links.resolvedType = emptyTypeLiteralType;
@ -5957,187 +5899,65 @@ namespace ts {
return links.resolvedType;
}
function getTypeFromSpreadTypeLiteral(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
let spread: Type = emptyObjectType;
let members: Map<Symbol>;
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
for (const member of (node as TypeLiteralNode).members) {
if (member.kind === SyntaxKind.SpreadTypeElement) {
if (members) {
const type = createAnonymousType(node.symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments);
members = undefined;
stringIndexInfo = undefined;
numberIndexInfo = undefined;
}
const type = getTypeFromTypeNode((member as SpreadTypeElement).type);
spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments);
}
else if (member.kind !== SyntaxKind.IndexSignature &&
member.kind !== SyntaxKind.CallSignature &&
member.kind !== SyntaxKind.ConstructSignature) {
// it is an error for spread types to include index, call or construct signatures
const flags = SymbolFlags.Property | SymbolFlags.Transient | (member.questionToken ? SymbolFlags.Optional : 0);
const text = getTextOfPropertyName(member.name);
const symbol = <TransientSymbol>createSymbol(flags, text);
symbol.declarations = [member];
symbol.valueDeclaration = member;
symbol.type = getTypeFromTypeNodeNoAlias((member as IndexSignatureDeclaration | PropertySignature | MethodSignature).type);
if (!members) {
members = createMap<Symbol>();
}
members[symbol.name] = symbol;
}
}
if (members || stringIndexInfo || numberIndexInfo) {
const type = createAnonymousType(node.symbol, members || emptySymbols, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments);
}
return spread;
}
/**
* Since the source of spread types are object literals and type literals, which are not binary,
* this function should be called in a left folding style, with left = previous result of getSpreadType
* and right = the new element to be spread.
*/
function getSpreadType(left: Type, right: Type, symbol: Symbol, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
const id = getTypeListId([left, right]);
if (id in spreadTypes) {
return spreadTypes[id];
}
// any spreads to any
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
return anyType;
}
// flatten intersections to objects if all member types are objects
if (left.flags & TypeFlags.Intersection) {
left = resolveObjectIntersection(left as IntersectionType);
}
if (right.flags & TypeFlags.Intersection) {
right = resolveObjectIntersection(right as IntersectionType);
}
// distribute unions
if (left.flags & TypeFlags.Union) {
const spreads = map((left as UnionType).types,
t => getSpreadType(t, right, symbol, aliasSymbol, aliasTypeArguments));
return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
}
if (right.flags & TypeFlags.Union) {
const spreads = map((right as UnionType).types,
t => getSpreadType(left, t, symbol, aliasSymbol, aliasTypeArguments));
return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
}
// skip primitives
if (left.flags & TypeFlags.Primitive && right.flags & TypeFlags.Primitive) {
return emptyObjectType;
}
else if (left.flags & TypeFlags.Primitive) {
return right;
}
else if (right.flags & TypeFlags.Primitive) {
return left;
}
// spread simplifications
if (left.flags & TypeFlags.Spread &&
right.flags & TypeFlags.TypeParameter &&
(left as SpreadType).right.flags & TypeFlags.TypeParameter &&
right.symbol === (left as SpreadType).right.symbol) {
// for types like T ... T, just return ... T
return left;
}
if (left.flags & TypeFlags.Spread &&
right.flags & TypeFlags.Object &&
(left as SpreadType).right.flags & TypeFlags.Object) {
// simplify two adjacent object types: T ... { x } ... { y } becomes T ... { x, y }
const simplified = getSpreadType(right, (left as SpreadType).right, symbol, aliasSymbol, aliasTypeArguments);
return getSpreadType((left as SpreadType).left, simplified, symbol, aliasSymbol, aliasTypeArguments);
}
if (right.flags & TypeFlags.Spread) {
// spread is right associative and associativity applies, so transform
// (T ... U) ... V to T ... (U ... V)
const rspread = right as SpreadType;
if (rspread.left === emptyObjectType) {
// ... U ... ({} ... T) => ... U ... T
return getSpreadType(left, rspread.right, symbol, aliasSymbol, aliasTypeArguments);
}
return getSpreadType(getSpreadType(left, rspread.left, symbol, aliasSymbol, aliasTypeArguments),
rspread.right, symbol, aliasSymbol, aliasTypeArguments);
}
// create an object type if left and right are both objects,
// otherwise create a spread type
if (right.flags & TypeFlags.Object && left.flags & TypeFlags.Object) {
const members = createMap<Symbol>();
const skippedPrivateMembers = createMap<boolean>();
const stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String));
const numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number));
const isFromSpread = right.symbol !== symbol;
for (const rightProp of getPropertiesOfType(right)) {
if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) {
skippedPrivateMembers[rightProp.name] = true;
}
else if (!(rightProp.flags & SymbolFlags.Method && isFromSpread) &&
!(rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor))) {
// skip methods from spreads and accessors with setters but no getters
members[rightProp.name] = rightProp;
}
}
for (const leftProp of getPropertiesOfType(left)) {
if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor)
|| leftProp.name in skippedPrivateMembers) {
continue;
}
if (leftProp.name in members) {
const rightProp = members[leftProp.name];
if (rightProp.flags & SymbolFlags.Optional) {
const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations);
const flags = SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | (leftProp.flags & SymbolFlags.Optional);
const result = <TransientSymbol>createSymbol(flags, leftProp.name);
result.syntheticKind = SyntheticSymbolKind.Spread;
result.leftSpread = leftProp;
result.rightSpread = rightProp;
result.declarations = declarations;
if (declarations.length) {
result.valueDeclaration = declarations[0];
}
result.isReadonly = isReadonlySymbol(leftProp) || isReadonlySymbol(rightProp);
members[leftProp.name] = result;
}
}
else {
members[leftProp.name] = leftProp;
}
}
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
const spread = spreadTypes[id] = createType(TypeFlags.Spread) as SpreadType;
Debug.assert(!!(left.flags & (TypeFlags.Spread | TypeFlags.Object)), "Left flags: " + left.flags.toString(2));
Debug.assert(!!(right.flags & (TypeFlags.TypeParameter | TypeFlags.Intersection | TypeFlags.Index | TypeFlags.IndexedAccess | TypeFlags.Object)), "Right flags: " + right.flags.toString(2));
spread.symbol = symbol;
spread.left = left as SpreadType | ResolvedType;
spread.right = right as TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType;
spread.aliasSymbol = aliasSymbol;
spread.aliasTypeArguments = aliasTypeArguments;
return spread;
}
function resolveObjectIntersection(intersection: IntersectionType): IntersectionType | ResolvedType {
if (find(intersection.types, t => !(t.flags & TypeFlags.Object))) {
return intersection;
}
const properties = getPropertiesOfType(intersection);
function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType {
Debug.assert(!!(left.flags & TypeFlags.Object) && !!(right.flags & TypeFlags.Object), "Only object types may be spread.");
const members = createMap<Symbol>();
for (const property of properties) {
members[property.name] = property;
const skippedPrivateMembers = createMap<boolean>();
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
if (left === emptyObjectType) {
// for the first spread element, left === emptyObjectType, so take the right's string indexer
stringIndexInfo = getIndexInfoOfType(right, IndexKind.String);
numberIndexInfo = getIndexInfoOfType(right, IndexKind.Number);
}
const stringIndex = getIndexInfoOfType(intersection, IndexKind.String);
const numberIndex = getIndexInfoOfType(intersection, IndexKind.Number);
return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndex, numberIndex);
else {
stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String));
numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number));
}
const isFromSpread = right.symbol !== symbol;
for (const rightProp of getPropertiesOfType(right)) {
if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) {
skippedPrivateMembers[rightProp.name] = true;
}
else if (!(rightProp.flags & SymbolFlags.Method && isFromSpread) &&
!(rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor))) {
// skip methods from spreads and accessors with setters but no getters
members[rightProp.name] = rightProp;
}
}
for (const leftProp of getPropertiesOfType(left)) {
if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor)
|| leftProp.name in skippedPrivateMembers) {
continue;
}
if (leftProp.name in members) {
const rightProp = members[leftProp.name];
if (rightProp.flags & SymbolFlags.Optional) {
const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations);
const flags = SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | (leftProp.flags & SymbolFlags.Optional);
const result = <TransientSymbol>createSymbol(flags, leftProp.name);
result.syntheticKind = SyntheticSymbolKind.Spread;
result.leftSpread = leftProp;
result.rightSpread = rightProp;
result.declarations = declarations;
if (declarations.length) {
result.valueDeclaration = declarations[0];
}
result.isReadonly = isReadonlySymbol(leftProp) || isReadonlySymbol(rightProp);
members[leftProp.name] = result;
}
}
else {
members[leftProp.name] = leftProp;
}
}
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
function createLiteralType(flags: TypeFlags, text: string) {
@ -6555,10 +6375,6 @@ namespace ts {
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
}
if (type.flags & TypeFlags.Spread) {
const spread = type as SpreadType;
return getSpreadType(instantiateType(spread.left, mapper), instantiateType(spread.right, mapper), type.symbol, type.aliasSymbol, mapper.targetTypes);
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));
}
@ -7109,30 +6925,7 @@ namespace ts {
}
}
if (source.flags & TypeFlags.Spread && target.flags & TypeFlags.Spread) {
// you only see this for spreads with type parameters
if (!(spreadTypeRelatedTo(source as SpreadType, target as SpreadType, /*atRightEdge*/ true))) {
if (reportErrors) {
reportRelationError(headMessage, source, target);
}
return Ternary.False;
}
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
const apparentSource = getApparentType(source);
if (result = objectTypeRelatedTo(apparentSource, source, getApparentType(target), reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
if (source.flags & TypeFlags.TypeParameter) {
if (target.flags & TypeFlags.Spread) {
// T is assignable to ...T
if (source.symbol === (target as SpreadType).right.symbol
&& (target as SpreadType).left === emptyObjectType) {
return Ternary.True;
}
}
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
if (!constraint || constraint.flags & TypeFlags.Any) {
@ -7184,32 +6977,6 @@ namespace ts {
return Ternary.False;
}
function spreadTypeRelatedTo(source: SpreadType, target: SpreadType, atRightEdge?: boolean): boolean {
// If the right side of a spread type is ObjectType, then the left side must be a Spread.
// Structural compatibility of the spreads' object types are checked separately in isRelatedTo,
// so just skip them for now.
if (source.right.flags & TypeFlags.Object || target.right.flags & TypeFlags.Object) {
return atRightEdge &&
spreadTypeRelatedTo(source.right.flags & TypeFlags.Object ? source.left as SpreadType : source,
target.right.flags & TypeFlags.Object ? target.left as SpreadType : target);
}
// If both right sides are type parameters, intersections, index types or indexed access types,
// then they must be identical for the spread types to be related.
// It also means that the left sides are either spread types or object types.
// if one left is object and the other is spread, that means the second has another type parameter. which isn't allowed
if (target.right !== source.right) {
return false;
}
if (source.left.flags & TypeFlags.Spread && target.left.flags & TypeFlags.Spread) {
// If the left sides are both spread types, then recursively check them.
return spreadTypeRelatedTo(source.left as SpreadType, target.left as SpreadType);
}
// If the left sides are both object types, then we should be at the end and both should be emptyObjectType.
// If not, we can't know what properties might have been overwritten, so fail.
return source.left === emptyObjectType && target.left === emptyObjectType;
}
function isIdenticalTo(source: Type, target: Type): Ternary {
let result: Ternary;
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
@ -11187,6 +10954,10 @@ namespace ts {
typeFlags = 0;
}
const type = checkExpression((memberDecl as SpreadElementExpression).expression);
if (!(type.flags & TypeFlags.Object)) {
error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
return unknownType;
}
spread = getSpreadType(spread, type, node.symbol);
continue;
}
@ -15423,13 +15194,6 @@ namespace ts {
checkTypeForDuplicateIndexSignatures(node);
checkObjectTypeForDuplicateDeclarations(node);
}
if (find(node.members, p => p.kind === SyntaxKind.SpreadTypeElement)) {
for (const signature of filter(node.members, p => p.kind === SyntaxKind.IndexSignature ||
p.kind === SyntaxKind.CallSignature ||
p.kind === SyntaxKind.ConstructSignature)) {
error(signature, Diagnostics.Type_literals_with_spreads_cannot_contain_index_call_or_construct_signatures);
}
}
}
}
@ -17487,9 +17251,7 @@ namespace ts {
// perform property check if property or indexer is declared in 'type'
// this allows to rule out cases when both property and indexer are inherited from the base class
let errorNode: Node;
if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName ||
prop.parent === containingType.symbol ||
containingType.flags & TypeFlags.Spread) {
if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) {
errorNode = prop.valueDeclaration;
}
else if (indexDeclaration) {
@ -20719,12 +20481,6 @@ namespace ts {
checkGrammarHeritageClause(heritageClause);
}
}
let result: TypeElement;
if (result = find(node.members, e => e.kind === SyntaxKind.SpreadTypeElement)) {
return grammarErrorOnNode(result, Diagnostics.Interface_declaration_cannot_contain_a_spread_property);
}
return false;
}

View File

@ -1138,13 +1138,6 @@ namespace ts {
writeLine();
}
function emitSpreadTypeElement(type: SpreadTypeElement) {
write("...");
emitType(type.type);
write(";");
writeLine();
}
function emitVariableDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) {
// If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
// so there is no check needed to see if declaration is visible
@ -1729,8 +1722,6 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return emitPropertyDeclaration(<PropertyDeclaration>node);
case SyntaxKind.SpreadTypeElement:
return emitSpreadTypeElement(node as SpreadTypeElement);
case SyntaxKind.EnumMember:
return emitEnumMemberDeclaration(<EnumMember>node);
case SyntaxKind.ExportAssignment:

View File

@ -1983,14 +1983,10 @@
"category": "Error",
"code": 2697
},
"Interface declaration cannot contain a spread property.": {
"Spread types may only be created from object types.": {
"category": "Error",
"code": 2698
},
"Type literals with spreads cannot contain index, call or construct signatures.": {
"category": "Error",
"code": 2699
},
"Rest types may only be created from object types.": {
"category": "Error",
"code": 2700

View File

@ -76,8 +76,6 @@ namespace ts {
visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
case SyntaxKind.SpreadElementExpression:
return visitNode(cbNode, (<SpreadElementExpression>node).expression);
case SyntaxKind.SpreadTypeElement:
return visitNode(cbNode, (node as SpreadTypeElement).type);
case SyntaxKind.Parameter:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
@ -2353,10 +2351,6 @@ namespace ts {
if (token() === SyntaxKind.OpenBracketToken) {
return true;
}
// spread elements are type members
if (token() === SyntaxKind.DotDotDotToken) {
return true;
}
// Try to get the first property-like token following all modifiers
if (isLiteralPropertyName()) {
idToken = token();
@ -2382,9 +2376,6 @@ namespace ts {
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
return parseSignatureMember(SyntaxKind.ConstructSignature);
}
if (token() === SyntaxKind.DotDotDotToken) {
return parseSpreadTypeElement();
}
const fullStart = getNodePos();
const modifiers = parseModifiers();
if (isIndexSignature()) {
@ -2393,14 +2384,6 @@ namespace ts {
return parsePropertyOrMethodSignature(fullStart, modifiers);
}
function parseSpreadTypeElement() {
const element = createNode(SyntaxKind.SpreadTypeElement, scanner.getStartPos()) as SpreadTypeElement;
parseTokenNode<Node>(); // parse `...`
element.type = parseType();
parseTypeMemberSemicolon();
return finishNode(element);
}
function isStartOfConstructSignature() {
nextToken();
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;

View File

@ -321,8 +321,6 @@ namespace ts {
PropertyAssignment,
ShorthandPropertyAssignment,
SpreadElementExpression,
SpreadTypeElement,
// Enum
EnumMember,
@ -665,11 +663,6 @@ namespace ts {
initializer?: Expression; // Optional initializer
}
// @kind(SyntaxKind.SpreadTypeElement)
export interface SpreadTypeElement extends TypeElement {
type: TypeNode;
}
// @kind(SyntaxKind.PropertyDeclaration)
export interface PropertyDeclaration extends ClassElement {
kind: SyntaxKind.PropertyDeclaration;
@ -2522,7 +2515,7 @@ namespace ts {
Merged = 0x02000000, // Merged symbol (created during program binding)
Transient = 0x04000000, // Transient symbol (created during type check)
Prototype = 0x08000000, // Prototype property (no source representation)
SyntheticProperty = 0x10000000, // Property in union, intersection or spread type
SyntheticProperty = 0x10000000, // Property in union or intersection type
Optional = 0x20000000, // Optional property
ExportStar = 0x40000000, // Export * declaration
@ -2712,7 +2705,6 @@ namespace ts {
ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
Spread = 1 << 24, // Spread types
/* @internal */
Nullable = Undefined | Null,
@ -2730,12 +2722,12 @@ namespace ts {
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
UnionOrIntersection = Union | Intersection,
StructuredType = Object | Union | Intersection | Spread,
StructuredType = Object | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | Spread,
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol,
NotUnionOrUnit = Any | ESSymbol | Object,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
@ -2850,12 +2842,6 @@ namespace ts {
export type StructuredType = ObjectType | UnionType | IntersectionType;
/* @internal */
export interface SpreadType extends Type {
left: SpreadType | ResolvedType;
right: TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType;
}
/* @internal */
// An instantiated anonymous type has a target and a mapper
export interface AnonymousType extends ObjectType {
@ -2869,7 +2855,7 @@ namespace ts {
}
/* @internal */
// Resolved object, spread, union, or intersection type
// Resolved object, union, or intersection type
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
members: SymbolTable; // Properties by name
properties: Symbol[]; // Properties

View File

@ -278,7 +278,7 @@ interface ObjectConstructor {
* @param target The target object to copy to.
* @param source The source object from which to copy properties.
*/
assign<T, U>(target: T, source: U): { ...T, ...U };
assign<T, U>(target: T, source: U): T & U;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
@ -287,7 +287,7 @@ interface ObjectConstructor {
* @param source1 The first source object from which to copy properties.
* @param source2 The second source object from which to copy properties.
*/
assign<T, U, V>(target: T, source1: U, source2: V): { ...T, ...U, ...V };
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
@ -297,7 +297,7 @@ interface ObjectConstructor {
* @param source2 The second source object from which to copy properties.
* @param source3 The third source object from which to copy properties.
*/
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): { ...T, ...U, ...V, ...W };
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a

View File

@ -35,13 +35,8 @@ let getter: { a: number, c: number } =
{ ...op, c: 7 }
getter.a = 12;
// null, undefined, functions and primitives result in { }
let spreadNull = { ...null };
let spreadUndefind = { ...undefined };
let spreadNum = { ...12 };
let spreadBool = { ...false };
// functions result in { }
let spreadFunc = { ...(function () { }) };
let spreadStr = { ...'foo' };
// methods are not enumerable
class C { p = 1; m() { } }
@ -80,22 +75,6 @@ let computedAfter: { a: number, b: string, "at the end": number } =
let a = 12;
let shortCutted: { a: number, b: string } = { ...o, a }
// generics
function f<T, U>(t: T, u: U): { ...T, ...U, id: string } {
return { ...t, ...u, id: 'id' };
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
let overlap: { id: string, a: number, b: string } =
f({ a: 1 }, { a: 2, b: 'extra' })
let overlapConflict: { id:string, a: string } =
f({ a: 1 }, { a: 'mismatch' })
let overwriteId: { id: string, a: number, c: number, d: string } =
f({ a: 1, id: true }, { c: 1, d: 'no' })
class D { m() { }; q = 2; }
let classesAreWrong: { id: string, ...C, ...D } =
f(new C(), new D())
//// [objectSpread.js]
@ -128,13 +107,8 @@ var propertyNested = __assign({ a: __assign({}, o) });
var op = { get a() { return 6; } };
var getter = __assign({}, op, { c: 7 });
getter.a = 12;
// null, undefined, functions and primitives result in { }
var spreadNull = __assign({}, null);
var spreadUndefind = __assign({}, undefined);
var spreadNum = __assign({}, 12);
var spreadBool = __assign({}, false);
// functions result in { }
var spreadFunc = __assign({}, (function () { }));
var spreadStr = __assign({}, 'foo');
// methods are not enumerable
var C = (function () {
function C() {
@ -167,21 +141,4 @@ var computedAfter = __assign({}, o, (_c = { b: 'yeah' }, _c['at the end'] = 14,
// shortcut syntax
var a = 12;
var shortCutted = __assign({}, o, { a: a });
// generics
function f(t, u) {
return __assign({}, t, u, { id: 'id' });
}
var exclusive = f({ a: 1, b: 'yes' }, { c: 'no', d: false });
var overlap = f({ a: 1 }, { a: 2, b: 'extra' });
var overlapConflict = f({ a: 1 }, { a: 'mismatch' });
var overwriteId = f({ a: 1, id: true }, { c: 1, d: 'no' });
var D = (function () {
function D() {
this.q = 2;
}
D.prototype.m = function () { };
;
return D;
}());
var classesAreWrong = f(new C(), new D());
var _a, _b, _c;

View File

@ -150,224 +150,127 @@ getter.a = 12;
>getter : Symbol(getter, Decl(objectSpread.ts, 32, 3))
>a : Symbol(a, Decl(objectSpread.ts, 32, 13))
// null, undefined, functions and primitives result in { }
let spreadNull = { ...null };
>spreadNull : Symbol(spreadNull, Decl(objectSpread.ts, 37, 3))
let spreadUndefind = { ...undefined };
>spreadUndefind : Symbol(spreadUndefind, Decl(objectSpread.ts, 38, 3))
let spreadNum = { ...12 };
>spreadNum : Symbol(spreadNum, Decl(objectSpread.ts, 39, 3))
let spreadBool = { ...false };
>spreadBool : Symbol(spreadBool, Decl(objectSpread.ts, 40, 3))
// functions result in { }
let spreadFunc = { ...(function () { }) };
>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 41, 3))
let spreadStr = { ...'foo' };
>spreadStr : Symbol(spreadStr, Decl(objectSpread.ts, 42, 3))
>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3))
// methods are not enumerable
class C { p = 1; m() { } }
>C : Symbol(C, Decl(objectSpread.ts, 42, 29))
>p : Symbol(C.p, Decl(objectSpread.ts, 45, 9))
>m : Symbol(C.m, Decl(objectSpread.ts, 45, 16))
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
>p : Symbol(C.p, Decl(objectSpread.ts, 40, 9))
>m : Symbol(C.m, Decl(objectSpread.ts, 40, 16))
let c: C = new C()
>c : Symbol(c, Decl(objectSpread.ts, 46, 3))
>C : Symbol(C, Decl(objectSpread.ts, 42, 29))
>C : Symbol(C, Decl(objectSpread.ts, 42, 29))
>c : Symbol(c, Decl(objectSpread.ts, 41, 3))
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
let spreadC: { p: number } = { ...c }
>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 47, 3))
>p : Symbol(p, Decl(objectSpread.ts, 47, 14))
>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 42, 3))
>p : Symbol(p, Decl(objectSpread.ts, 42, 14))
// own methods are enumerable
let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } };
>cplus : Symbol(cplus, Decl(objectSpread.ts, 50, 3))
>p : Symbol(p, Decl(objectSpread.ts, 50, 12))
>plus : Symbol(plus, Decl(objectSpread.ts, 50, 23))
>plus : Symbol(plus, Decl(objectSpread.ts, 50, 48))
>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3))
>p : Symbol(p, Decl(objectSpread.ts, 45, 12))
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 48))
cplus.plus();
>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 50, 23))
>cplus : Symbol(cplus, Decl(objectSpread.ts, 50, 3))
>plus : Symbol(plus, Decl(objectSpread.ts, 50, 23))
>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3))
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
// new field's type conflicting with existing field is OK
let changeTypeAfter: { a: string, b: string } =
>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 54, 3))
>a : Symbol(a, Decl(objectSpread.ts, 54, 22))
>b : Symbol(b, Decl(objectSpread.ts, 54, 33))
>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 49, 3))
>a : Symbol(a, Decl(objectSpread.ts, 49, 22))
>b : Symbol(b, Decl(objectSpread.ts, 49, 33))
{ ...o, a: 'wrong type?' }
>a : Symbol(a, Decl(objectSpread.ts, 55, 11))
>a : Symbol(a, Decl(objectSpread.ts, 50, 11))
let changeTypeBefore: { a: number, b: string } =
>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 56, 3))
>a : Symbol(a, Decl(objectSpread.ts, 56, 23))
>b : Symbol(b, Decl(objectSpread.ts, 56, 34))
>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 51, 3))
>a : Symbol(a, Decl(objectSpread.ts, 51, 23))
>b : Symbol(b, Decl(objectSpread.ts, 51, 34))
{ a: 'wrong type?', ...o };
>a : Symbol(a, Decl(objectSpread.ts, 57, 5))
>a : Symbol(a, Decl(objectSpread.ts, 52, 5))
let changeTypeBoth: { a: string, b: number } =
>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 58, 3))
>a : Symbol(a, Decl(objectSpread.ts, 58, 21))
>b : Symbol(b, Decl(objectSpread.ts, 58, 32))
>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 53, 3))
>a : Symbol(a, Decl(objectSpread.ts, 53, 21))
>b : Symbol(b, Decl(objectSpread.ts, 53, 32))
{ ...o, ...swap };
// optional
let definiteBoolean: { sn: boolean };
>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 62, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 62, 22))
>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 57, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 57, 22))
let definiteString: { sn: string };
>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 63, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 63, 21))
>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 58, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 58, 21))
let optionalString: { sn?: string };
>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 64, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 64, 21))
>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 59, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 59, 21))
let optionalNumber: { sn?: number };
>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 65, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 65, 21))
>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 60, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 60, 21))
let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber };
>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 66, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 66, 25))
>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 61, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 61, 25))
let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber };
>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 67, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 67, 30))
>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 62, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 62, 30))
let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber };
>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 68, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 68, 18))
>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 63, 3))
>sn : Symbol(sn, Decl(objectSpread.ts, 63, 18))
// computed property
let computedFirst: { a: number, b: string, "before everything": number } =
>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 71, 3))
>a : Symbol(a, Decl(objectSpread.ts, 71, 20))
>b : Symbol(b, Decl(objectSpread.ts, 71, 31))
>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 66, 3))
>a : Symbol(a, Decl(objectSpread.ts, 66, 20))
>b : Symbol(b, Decl(objectSpread.ts, 66, 31))
{ ['before everything']: 12, ...o, b: 'yes' }
>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 72, 5))
>b : Symbol(b, Decl(objectSpread.ts, 72, 38))
>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 67, 5))
>b : Symbol(b, Decl(objectSpread.ts, 67, 38))
let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } =
>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 73, 3))
>a : Symbol(a, Decl(objectSpread.ts, 73, 21))
>b : Symbol(b, Decl(objectSpread.ts, 73, 32))
>c : Symbol(c, Decl(objectSpread.ts, 73, 43))
>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 68, 3))
>a : Symbol(a, Decl(objectSpread.ts, 68, 21))
>b : Symbol(b, Decl(objectSpread.ts, 68, 32))
>c : Symbol(c, Decl(objectSpread.ts, 68, 43))
{ ...o, ['in the middle']: 13, b: 'maybe?', ...o2 }
>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 74, 11))
>b : Symbol(b, Decl(objectSpread.ts, 74, 34))
>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 69, 11))
>b : Symbol(b, Decl(objectSpread.ts, 69, 34))
let computedAfter: { a: number, b: string, "at the end": number } =
>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 75, 3))
>a : Symbol(a, Decl(objectSpread.ts, 75, 20))
>b : Symbol(b, Decl(objectSpread.ts, 75, 31))
>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 70, 3))
>a : Symbol(a, Decl(objectSpread.ts, 70, 20))
>b : Symbol(b, Decl(objectSpread.ts, 70, 31))
{ ...o, b: 'yeah', ['at the end']: 14 }
>b : Symbol(b, Decl(objectSpread.ts, 76, 11))
>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 76, 22))
>b : Symbol(b, Decl(objectSpread.ts, 71, 11))
>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 71, 22))
// shortcut syntax
let a = 12;
>a : Symbol(a, Decl(objectSpread.ts, 78, 3))
>a : Symbol(a, Decl(objectSpread.ts, 73, 3))
let shortCutted: { a: number, b: string } = { ...o, a }
>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 79, 3))
>a : Symbol(a, Decl(objectSpread.ts, 79, 18))
>b : Symbol(b, Decl(objectSpread.ts, 79, 29))
>a : Symbol(a, Decl(objectSpread.ts, 79, 51))
>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 74, 3))
>a : Symbol(a, Decl(objectSpread.ts, 74, 18))
>b : Symbol(b, Decl(objectSpread.ts, 74, 29))
>a : Symbol(a, Decl(objectSpread.ts, 74, 51))
// generics
function f<T, U>(t: T, u: U): { ...T, ...U, id: string } {
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>T : Symbol(T, Decl(objectSpread.ts, 82, 11))
>U : Symbol(U, Decl(objectSpread.ts, 82, 13))
>t : Symbol(t, Decl(objectSpread.ts, 82, 17))
>T : Symbol(T, Decl(objectSpread.ts, 82, 11))
>u : Symbol(u, Decl(objectSpread.ts, 82, 22))
>U : Symbol(U, Decl(objectSpread.ts, 82, 13))
>T : Symbol(T, Decl(objectSpread.ts, 82, 11))
>U : Symbol(U, Decl(objectSpread.ts, 82, 13))
>id : Symbol(id, Decl(objectSpread.ts, 82, 43))
return { ...t, ...u, id: 'id' };
>id : Symbol(id, Decl(objectSpread.ts, 83, 24))
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
>exclusive : Symbol(exclusive, Decl(objectSpread.ts, 85, 3))
>id : Symbol(id, Decl(objectSpread.ts, 85, 16))
>a : Symbol(a, Decl(objectSpread.ts, 85, 28))
>b : Symbol(b, Decl(objectSpread.ts, 85, 39))
>c : Symbol(c, Decl(objectSpread.ts, 85, 50))
>d : Symbol(d, Decl(objectSpread.ts, 85, 61))
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>a : Symbol(a, Decl(objectSpread.ts, 86, 7))
>b : Symbol(b, Decl(objectSpread.ts, 86, 13))
>c : Symbol(c, Decl(objectSpread.ts, 86, 27))
>d : Symbol(d, Decl(objectSpread.ts, 86, 36))
let overlap: { id: string, a: number, b: string } =
>overlap : Symbol(overlap, Decl(objectSpread.ts, 87, 3))
>id : Symbol(id, Decl(objectSpread.ts, 87, 14))
>a : Symbol(a, Decl(objectSpread.ts, 87, 26))
>b : Symbol(b, Decl(objectSpread.ts, 87, 37))
f({ a: 1 }, { a: 2, b: 'extra' })
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>a : Symbol(a, Decl(objectSpread.ts, 88, 7))
>a : Symbol(a, Decl(objectSpread.ts, 88, 17))
>b : Symbol(b, Decl(objectSpread.ts, 88, 23))
let overlapConflict: { id:string, a: string } =
>overlapConflict : Symbol(overlapConflict, Decl(objectSpread.ts, 89, 3))
>id : Symbol(id, Decl(objectSpread.ts, 89, 22))
>a : Symbol(a, Decl(objectSpread.ts, 89, 33))
f({ a: 1 }, { a: 'mismatch' })
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>a : Symbol(a, Decl(objectSpread.ts, 90, 7))
>a : Symbol(a, Decl(objectSpread.ts, 90, 17))
let overwriteId: { id: string, a: number, c: number, d: string } =
>overwriteId : Symbol(overwriteId, Decl(objectSpread.ts, 91, 3))
>id : Symbol(id, Decl(objectSpread.ts, 91, 18))
>a : Symbol(a, Decl(objectSpread.ts, 91, 30))
>c : Symbol(c, Decl(objectSpread.ts, 91, 41))
>d : Symbol(d, Decl(objectSpread.ts, 91, 52))
f({ a: 1, id: true }, { c: 1, d: 'no' })
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>a : Symbol(a, Decl(objectSpread.ts, 92, 7))
>id : Symbol(id, Decl(objectSpread.ts, 92, 13))
>c : Symbol(c, Decl(objectSpread.ts, 92, 27))
>d : Symbol(d, Decl(objectSpread.ts, 92, 33))
class D { m() { }; q = 2; }
>D : Symbol(D, Decl(objectSpread.ts, 92, 44))
>m : Symbol(D.m, Decl(objectSpread.ts, 94, 9))
>q : Symbol(D.q, Decl(objectSpread.ts, 94, 18))
let classesAreWrong: { id: string, ...C, ...D } =
>classesAreWrong : Symbol(classesAreWrong, Decl(objectSpread.ts, 95, 3))
>id : Symbol(id, Decl(objectSpread.ts, 95, 22))
>C : Symbol(C, Decl(objectSpread.ts, 42, 29))
>D : Symbol(D, Decl(objectSpread.ts, 92, 44))
f(new C(), new D())
>f : Symbol(f, Decl(objectSpread.ts, 79, 55))
>C : Symbol(C, Decl(objectSpread.ts, 42, 29))
>D : Symbol(D, Decl(objectSpread.ts, 92, 44))

View File

@ -223,36 +223,13 @@ getter.a = 12;
>a : number
>12 : 12
// null, undefined, functions and primitives result in { }
let spreadNull = { ...null };
>spreadNull : {}
>{ ...null } : {}
>null : null
let spreadUndefind = { ...undefined };
>spreadUndefind : {}
>{ ...undefined } : {}
>undefined : any
let spreadNum = { ...12 };
>spreadNum : {}
>{ ...12 } : {}
let spreadBool = { ...false };
>spreadBool : {}
>{ ...false } : {}
>false : false
// functions result in { }
let spreadFunc = { ...(function () { }) };
>spreadFunc : {}
>{ ...(function () { }) } : {}
>(function () { }) : () => void
>function () { } : () => void
let spreadStr = { ...'foo' };
>spreadStr : {}
>{ ...'foo' } : {}
// methods are not enumerable
class C { p = 1; m() { } }
>C : C
@ -421,119 +398,4 @@ let shortCutted: { a: number, b: string } = { ...o, a }
>o : any
>a : number
// generics
function f<T, U>(t: T, u: U): { ...T, ...U, id: string } {
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>T : T
>U : U
>t : T
>T : T
>u : U
>U : U
>T : T
>U : U
>id : string
return { ...t, ...u, id: 'id' };
>{ ...t, ...u, id: 'id' } : { ...T; ...U; id: string; }
>t : any
>u : any
>id : string
>'id' : "id"
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
>exclusive : { id: string; a: number; b: string; c: string; d: boolean; }
>id : string
>a : number
>b : string
>c : string
>d : boolean
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
>f({ a: 1, b: 'yes' }, { c: 'no', d: false }) : { id: string; c: string; d: boolean; a: number; b: string; }
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>{ a: 1, b: 'yes' } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>'yes' : "yes"
>{ c: 'no', d: false } : { c: string; d: false; }
>c : string
>'no' : "no"
>d : boolean
>false : false
let overlap: { id: string, a: number, b: string } =
>overlap : { id: string; a: number; b: string; }
>id : string
>a : number
>b : string
f({ a: 1 }, { a: 2, b: 'extra' })
>f({ a: 1 }, { a: 2, b: 'extra' }) : { id: string; a: number; b: string; }
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 2, b: 'extra' } : { a: number; b: string; }
>a : number
>2 : 2
>b : string
>'extra' : "extra"
let overlapConflict: { id:string, a: string } =
>overlapConflict : { id: string; a: string; }
>id : string
>a : string
f({ a: 1 }, { a: 'mismatch' })
>f({ a: 1 }, { a: 'mismatch' }) : { id: string; a: string; }
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 'mismatch' } : { a: string; }
>a : string
>'mismatch' : "mismatch"
let overwriteId: { id: string, a: number, c: number, d: string } =
>overwriteId : { id: string; a: number; c: number; d: string; }
>id : string
>a : number
>c : number
>d : string
f({ a: 1, id: true }, { c: 1, d: 'no' })
>f({ a: 1, id: true }, { c: 1, d: 'no' }) : { id: string; c: number; d: string; a: number; }
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>{ a: 1, id: true } : { a: number; id: true; }
>a : number
>1 : 1
>id : boolean
>true : true
>{ c: 1, d: 'no' } : { c: number; d: string; }
>c : number
>1 : 1
>d : string
>'no' : "no"
class D { m() { }; q = 2; }
>D : D
>m : () => void
>q : number
>2 : 2
let classesAreWrong: { id: string, ...C, ...D } =
>classesAreWrong : { q: number; p: number; id: string; }
>id : string
>C : C
>D : D
f(new C(), new D())
>f(new C(), new D()) : { id: string; q: number; p: number; }
>f : <T, U>(t: T, u: U) => { ...T; ...U; id: string; }
>new C() : C
>C : typeof C
>new D() : D
>D : typeof D

View File

@ -1,148 +0,0 @@
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(9,5): error TS2322: Type '{ ...U }' is not assignable to type 'U'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(10,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...V; ...U; ...T }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(11,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...T; ...V }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(12,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...V }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(13,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...V }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(14,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(16,11): error TS2322: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(19,11): error TS2322: Type '{}' is not assignable to type '{ ...T; ...U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(26,11): error TS2322: Type '{ sn?: boolean; ...T; sn?: string | number; }' is not assignable to type '{ ...T; sn?: string | number | boolean; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(32,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(34,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; second: string; ...T; third: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(36,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(38,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; second: string; secondsecond: string; third: string; ...T; ...U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(42,11): error TS2322: Type '{ firrrrrrst: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(44,11): error TS2322: Type '{ first: string; ...T; ssssssssecond: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(46,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; thirrrrrrrd: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(57,5): error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...keyof T }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(58,5): error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...keyof U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(61,5): error TS2322: Type '{ ...K }' is not assignable to type '{ ...keyof T }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(62,5): error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...K }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(63,5): error TS2322: Type '{ ...J }' is not assignable to type '{ ...keyof U }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(64,5): error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...J }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(70,5): error TS2322: Type '{ ...U[J] }' is not assignable to type '{ ...T[K] }'.
tests/cases/conformance/types/spread/objectSpreadGeneric.ts(71,5): error TS2322: Type '{ ...T[K] }' is not assignable to type '{ ...U[J] }'.
==== tests/cases/conformance/types/spread/objectSpreadGeneric.ts (24 errors) ====
function f<T, U, V>(t: T, u: U, v: V): void {
let o: { ...T, ...U, ...V };
let uus: { ...U, ...U};
let us: { ...U };
const same: { ...T, ...U, ...V } = o; // ok
uus = us; // ok, multiple spreads are equivalent to a single one
us = uus; // ok, multiple spreads are equivalent to a single one
us = u; // ok, type has at least all the properties of the spread
u = us; // error, might be missing a ton of stuff
~
!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'.
const reversed: { ...V, ...U, ...T } = o; // error, reversed
~~~~~~~~
!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...V; ...U; ...T }'.
const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed
~~~~~~~~~
!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...T; ...V }'.
const missingT: { ...U, ...V } = o; // error, missing T
~~~~~~~~
!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...V }'.
const missingU: { ...T, ...V } = o; // error, missing U
~~~~~~~~
!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...V }'.
const missingV: { ...T, ...U } = o; // error, missing V
~~~~~~~~
!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...U }'.
const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok
const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable
~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'.
const emptyTarget: { } = { ...t, ...u } // ok
const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T)
~~~~~~~~~~~
!!! error TS2322: Type '{}' is not assignable to type '{ ...T; ...U }'.
// error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to
// T ... { sn?: number | string | boolean }
let optionalNumber: { sn?: number };
let optionalString: { sn?: string };
let optionalBoolean: { sn?: boolean };
const unionCutoff: { ...T, sn?: number | string | boolean } =
~~~~~~~~~~~
!!! error TS2322: Type '{ sn?: boolean; ...T; sn?: string | number; }' is not assignable to type '{ ...T; sn?: string | number | boolean; }'.
{ ...optionalBoolean, ...t, ...optionalString, ...optionalNumber }
unionCutoff.sn; // ok
const optionalCutoff = { ...t, ...optionalNumber }; // ok
optionalCutoff.sn; // ok
const interspersed: { first: string, ...T, second: string, ...U, third: string } =
~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const interspersedMissingU: { first: string, second: string, ...T, third: string } =
~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; second: string; ...T; third: string; }'.
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing
const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } =
~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }'.
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } =
~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; second: string; secondsecond: string; third: string; ...T; ...U }'.
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } =
~~~~~~~~~~~~~
!!! error TS2322: Type '{ firrrrrrst: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
{ firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } =
~~~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; ssssssssecond: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
{ first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable
const mismatchLast: { first: string, ...T, second: string, ...U, third: string } =
~~~~~~~~~~~~
!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; thirrrrrrrd: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'.
{ first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable
}
function indexAccessedTest<T, K extends keyof T, U, J extends keyof U>(t: T, u: U, key1: K, key2: J) {
let k1: { ...keyof T };
let k2: { ...keyof U };
let k3: { ...K };
let k4: { ...J };
k1 = k1; // ok
k2 = k2; // ok
k1 = k2; // error
~~
!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...keyof T }'.
k2 = k1; // error
~~
!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...keyof U }'.
k3 = k3; // ok
k4 = k4; // ok
k1 = k3; // error
~~
!!! error TS2322: Type '{ ...K }' is not assignable to type '{ ...keyof T }'.
k3 = k1; // error
~~
!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...K }'.
k2 = k4; // error
~~
!!! error TS2322: Type '{ ...J }' is not assignable to type '{ ...keyof U }'.
k4 = k2; // error
~~
!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...J }'.
let i1: { ...T[K] };
let i2: { ...U[J] };
i1 = i1; // ok
i2 = i2; // ok
i1 = i2; // error
~~
!!! error TS2322: Type '{ ...U[J] }' is not assignable to type '{ ...T[K] }'.
i2 = i1; // error
~~
!!! error TS2322: Type '{ ...T[K] }' is not assignable to type '{ ...U[J] }'.
}

View File

@ -1,141 +0,0 @@
//// [objectSpreadGeneric.ts]
function f<T, U, V>(t: T, u: U, v: V): void {
let o: { ...T, ...U, ...V };
let uus: { ...U, ...U};
let us: { ...U };
const same: { ...T, ...U, ...V } = o; // ok
uus = us; // ok, multiple spreads are equivalent to a single one
us = uus; // ok, multiple spreads are equivalent to a single one
us = u; // ok, type has at least all the properties of the spread
u = us; // error, might be missing a ton of stuff
const reversed: { ...V, ...U, ...T } = o; // error, reversed
const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed
const missingT: { ...U, ...V } = o; // error, missing T
const missingU: { ...T, ...V } = o; // error, missing U
const missingV: { ...T, ...U } = o; // error, missing V
const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok
const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable
const emptyTarget: { } = { ...t, ...u } // ok
const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T)
// error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to
// T ... { sn?: number | string | boolean }
let optionalNumber: { sn?: number };
let optionalString: { sn?: string };
let optionalBoolean: { sn?: boolean };
const unionCutoff: { ...T, sn?: number | string | boolean } =
{ ...optionalBoolean, ...t, ...optionalString, ...optionalNumber }
unionCutoff.sn; // ok
const optionalCutoff = { ...t, ...optionalNumber }; // ok
optionalCutoff.sn; // ok
const interspersed: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const interspersedMissingU: { first: string, second: string, ...T, third: string } =
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing
const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } =
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } =
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } =
{ firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable
const mismatchLast: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable
}
function indexAccessedTest<T, K extends keyof T, U, J extends keyof U>(t: T, u: U, key1: K, key2: J) {
let k1: { ...keyof T };
let k2: { ...keyof U };
let k3: { ...K };
let k4: { ...J };
k1 = k1; // ok
k2 = k2; // ok
k1 = k2; // error
k2 = k1; // error
k3 = k3; // ok
k4 = k4; // ok
k1 = k3; // error
k3 = k1; // error
k2 = k4; // error
k4 = k2; // error
let i1: { ...T[K] };
let i2: { ...U[J] };
i1 = i1; // ok
i2 = i2; // ok
i1 = i2; // error
i2 = i1; // error
}
//// [objectSpreadGeneric.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
function f(t, u, v) {
var o;
var uus;
var us;
var same = o; // ok
uus = us; // ok, multiple spreads are equivalent to a single one
us = uus; // ok, multiple spreads are equivalent to a single one
us = u; // ok, type has at least all the properties of the spread
u = us; // error, might be missing a ton of stuff
var reversed = o; // error, reversed
var reversed2 = o; // error, U and T are still reversed
var missingT = o; // error, missing T
var missingU = o; // error, missing U
var missingV = o; // error, missing V
var atEnd = __assign({}, t, u, { second: 'foo' }); // ok
var atBeginning = __assign({ first: 'foo' }, t, u); // error, not assignable
var emptyTarget = __assign({}, t, u); // ok
var emptySource = {}; // error, {} is not assignable to U (or T)
// error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to
// T ... { sn?: number | string | boolean }
var optionalNumber;
var optionalString;
var optionalBoolean;
var unionCutoff = __assign({}, optionalBoolean, t, optionalString, optionalNumber);
unionCutoff.sn; // ok
var optionalCutoff = __assign({}, t, optionalNumber); // ok
optionalCutoff.sn; // ok
var interspersed = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3' }); // error, not assignable
var interspersedMissingU = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3' }); // error, 'U' is missing
var interspersedOrder1 = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3', secondsecond: 'false' }); // error, not assignable
var interspersedOrder2 = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3', secondsecond: 'false' }); // error, not assignable
var mismatchFirst = __assign({ firrrrrrst: '1' }, t, { second: '2' }, u, { third: '3' }); // error, not assignable
var mismatchSecond = __assign({ first: '1' }, t, { ssssssssecond: '2' }, u, { third: '3' }); // error, not assignable
var mismatchLast = __assign({ first: '1' }, t, { second: '2' }, u, { thirrrrrrrd: '3' }); // error, not assignable
}
function indexAccessedTest(t, u, key1, key2) {
var k1;
var k2;
var k3;
var k4;
k1 = k1; // ok
k2 = k2; // ok
k1 = k2; // error
k2 = k1; // error
k3 = k3; // ok
k4 = k4; // ok
k1 = k3; // error
k3 = k1; // error
k2 = k4; // error
k4 = k2; // error
var i1;
var i2;
i1 = i1; // ok
i2 = i2; // ok
i1 = i2; // error
i2 = i1; // error
}

View File

@ -1,35 +0,0 @@
tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(6,39): error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(24,20): error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
==== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts (2 errors) ====
class C {
a: number;
c: boolean;
}
// index signatures are not allowed in object literals with spread types
let c: { ...C, b: string, c?: string, [n: number]: string };
~~~~~~~~~~~~~~~~~~~
!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
let n: number = c.a;
let s: string = c[12];
interface Indexed {
[n: string]: number;
a: number;
}
let i: { ...Indexed, b: number };
n = i[101];
n = i.b;
interface Indexed2 {
[n: string]: boolean;
c: boolean;
}
let ii: { ...Indexed, ...Indexed2, b: boolean, d: number };
let nb: number | boolean = ii[1001];
function f<T>(t: T) {
let i: { ...T, [n: number]: string };
~~~~~~~~~~~~~~~~~~~
!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
}

View File

@ -1,46 +1,36 @@
//// [objectSpreadIndexSignature.ts]
class C {
a: number;
c: boolean;
}
// index signatures are not allowed in object literals with spread types
let c: { ...C, b: string, c?: string, [n: number]: string };
let n: number = c.a;
let s: string = c[12];
interface Indexed {
[n: string]: number;
a: number;
}
let i: { ...Indexed, b: number };
n = i[101];
n = i.b;
interface Indexed2 {
[n: string]: boolean;
c: boolean;
}
let ii: { ...Indexed, ...Indexed2, b: boolean, d: number };
let nb: number | boolean = ii[1001];
function f<T>(t: T) {
let i: { ...T, [n: number]: string };
}
let indexed: Indexed;
let indexed2: Indexed2;
let i = { ...indexed, b: 11 };
// only indexed has indexer, so i[101]: any
i[101];
let ii = { ...indexed, ...indexed2 };
// both have indexer, so i[1001]: number | boolean
ii[1001];
//// [objectSpreadIndexSignature.js]
var C = (function () {
function C() {
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return C;
}());
// index signatures are not allowed in object literals with spread types
var c;
var n = c.a;
var s = c[12];
var i;
n = i[101];
n = i.b;
var ii;
var nb = ii[1001];
function f(t) {
var i;
}
return t;
};
var indexed;
var indexed2;
var i = __assign({}, indexed, { b: 11 });
// only indexed has indexer, so i[101]: any
i[101];
var ii = __assign({}, indexed, indexed2);
// both have indexer, so i[1001]: number | boolean
ii[1001];

View File

@ -0,0 +1,42 @@
=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts ===
interface Indexed {
>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0))
[n: string]: number;
>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 1, 5))
a: number;
>a : Symbol(Indexed.a, Decl(objectSpreadIndexSignature.ts, 1, 24))
}
interface Indexed2 {
>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1))
[n: string]: boolean;
>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 5, 5))
c: boolean;
>c : Symbol(Indexed2.c, Decl(objectSpreadIndexSignature.ts, 5, 25))
}
let indexed: Indexed;
>indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3))
>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0))
let indexed2: Indexed2;
>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 9, 3))
>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1))
let i = { ...indexed, b: 11 };
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 21))
// only indexed has indexer, so i[101]: any
i[101];
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3))
let ii = { ...indexed, ...indexed2 };
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3))
// both have indexer, so i[1001]: number | boolean
ii[1001];
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3))

View File

@ -0,0 +1,52 @@
=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts ===
interface Indexed {
>Indexed : Indexed
[n: string]: number;
>n : string
a: number;
>a : number
}
interface Indexed2 {
>Indexed2 : Indexed2
[n: string]: boolean;
>n : string
c: boolean;
>c : boolean
}
let indexed: Indexed;
>indexed : Indexed
>Indexed : Indexed
let indexed2: Indexed2;
>indexed2 : Indexed2
>Indexed2 : Indexed2
let i = { ...indexed, b: 11 };
>i : { b: number; a: number; }
>{ ...indexed, b: 11 } : { b: number; a: number; }
>indexed : any
>b : number
>11 : 11
// only indexed has indexer, so i[101]: any
i[101];
>i[101] : any
>i : { b: number; a: number; }
>101 : 101
let ii = { ...indexed, ...indexed2 };
>ii : { [x: string]: number | boolean; c: boolean; a: number; }
>{ ...indexed, ...indexed2 } : { [x: string]: number | boolean; c: boolean; a: number; }
>indexed : any
>indexed2 : any
// both have indexer, so i[1001]: number | boolean
ii[1001];
>ii[1001] : number | boolean
>ii : { [x: string]: number | boolean; c: boolean; a: number; }
>1001 : 1001

View File

@ -1,30 +1,26 @@
tests/cases/conformance/types/spread/objectSpreadNegative.ts(11,21): error TS2339: Property 'x' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(14,5): error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(13,21): error TS2339: Property 'x' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(16,5): error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'.
Property 'sn' is optional in type '{ sn?: string | number; }' but required in type '{ sn: string | number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(20,5): error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(23,1): error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'.
Property 'b' is missing in type '{ s: string; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(22,1): error TS2322: Type 'Bool' is not assignable to type '{ s: string; b: boolean; }'.
Property 's' is missing in type 'Bool'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,36): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,53): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(30,12): error TS2339: Property 'null' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,17): error TS2339: Property 'undefined' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(36,11): error TS2339: Property 'toFixed' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(38,11): error TS2339: Property 'toFixed' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(40,11): error TS2339: Property 'length' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(41,11): error TS2339: Property 'charAt' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(45,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(49,12): error TS2339: Property 'b' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(55,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,48): error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,69): error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ x: number; }' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(64,9): error TS2322: Type '{ ...T & V }' is not assignable to type '{ ...T & U }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS2322: Type '{ ...U }' is not assignable to type 'U'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,1): error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'.
Property 's' is missing in type '{ b: boolean; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,36): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,53): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,20): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(33,24): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(34,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(35,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(37,20): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(39,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(44,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(48,12): error TS2339: Property 'b' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(54,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(61,14): error TS2698: Spread types may only be created from object types.
==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (21 errors) ====
==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (17 errors) ====
let o = { a: 1, b: 'no' }
/// private propagates
@ -34,7 +30,9 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232
class PublicX {
public x: number;
}
let o2: { ...PublicX, ...PrivateOptionalX };
let publicX: PublicX;
let privateOptionalX: PrivateOptionalX;
let o2 = { ...publicX, ...privateOptionalX };
let sn: number = o2.x; // error, x is private
~
!!! error TS2339: Property 'x' does not exist on type '{}'.
@ -49,15 +47,16 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232
// assignability as target
interface Bool { b: boolean };
interface Str { s: string };
let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b'
~~~~~~
let spread = { ...{ b: true }, ...{s: "foo" } };
spread = { s: "foo" }; // error, missing 'b'
~~~~~~
!!! error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'.
!!! error TS2322: Property 'b' is missing in type '{ s: string; }'.
let b: Bool;
let b = { b: false };
spread = b; // error, missing 's'
~~~~~~
!!! error TS2322: Type 'Bool' is not assignable to type '{ s: string; b: boolean; }'.
!!! error TS2322: Property 's' is missing in type 'Bool'.
!!! error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'.
!!! error TS2322: Property 's' is missing in type '{ b: boolean; }'.
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
@ -67,34 +66,30 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232
!!! error TS2300: Duplicate identifier 'b'.
let duplicatedSpread = { ...o, ...o }
// null and undefined are just skipped
let spreadNull = { ...null }
spreadNull.null;
~~~~
!!! error TS2339: Property 'null' does not exist on type '{}'.
let spreadUndefined = { ...undefined }
spreadUndefined.undefined;
~~~~~~~~~
!!! error TS2339: Property 'undefined' does not exist on type '{}'.
// primitives and functions are skipped
// null, undefined and primitives are not allowed
let spreadNull = { ...null };
~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
let spreadUndefind = { ...undefined };
~~~~~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
let spreadNum = { ...12 };
spreadNum.toFixed(); // error, no methods from number
~~~~~~~
!!! error TS2339: Property 'toFixed' does not exist on type '{}'.
~~~~~
!!! error TS2698: Spread types may only be created from object types.
let spreadSum = { ...1 + 1 };
~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
spreadSum.toFixed(); // error, no methods from number
~~~~~~~
!!! error TS2339: Property 'toFixed' does not exist on type '{}'.
let spreadStr = { ...'foo' };
spreadStr.length; // error, no 'length'
~~~~~~
!!! error TS2339: Property 'length' does not exist on type '{}'.
spreadStr.charAt(1); // error, no methods either
~~~~~~
!!! error TS2339: Property 'charAt' does not exist on type '{}'.
let spreadBool = { ...true };
let spreadBool = { ...false };
~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
spreadBool.valueOf(); // error, what were you thinking?
let spreadStr = { ...'foo' };
~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
spreadStr.length; // error, no 'length'
spreadStr.charAt(1); // error, no methods either
// functions are skipped
let spreadFunc = { ...function () { } }
spreadFunc(); // error, no call signature
~~~~~~~~~~~~
@ -114,27 +109,23 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232
~
!!! error TS2339: Property 'm' does not exist on type '{ p: number; }'.
let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) };
~~~~~~~~~~~~~~~~~~~~
!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
~~~~~~~~~~~~~~~
!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures.
callableConstructableSpread(12); // error, no call signature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ x: number; }' has no compatible call signatures.
new callableConstructableSpread(12); // error, no construct signature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
function override<T,U,V>(initial: U, override: U, t: T, v: V): U {
// { ... T & V } is not assignable to { ... T & U }
let tvs: { ...T & V };
let mistake: { ...T & U } = tvs;
~~~~~~~
!!! error TS2322: Type '{ ...T & V }' is not assignable to type '{ ...T & U }'.
// { ...U } is not assignable to U
return { ...initial, ...override };
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'.
// generics
function f<T, U>(t: T, u: U) {
return { ...t, ...u, id: 'id' };
~~~~
!!! error TS2698: Spread types may only be created from object types.
}
function override<U>(initial: U, override: U): U {
return { ...initial, ...override };
~~~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
let overlap: { id: string, a: number, b: string } =
f({ a: 1 }, { a: 2, b: 'extra' })
let overlapConflict: { id:string, a: string } =
f({ a: 1 }, { a: 'mismatch' })
let overwriteId: { id: string, a: number, c: number, d: string } =
f({ a: 1, id: true }, { c: 1, d: 'no' })

View File

@ -8,7 +8,9 @@ class PrivateOptionalX {
class PublicX {
public x: number;
}
let o2: { ...PublicX, ...PrivateOptionalX };
let publicX: PublicX;
let privateOptionalX: PrivateOptionalX;
let o2 = { ...publicX, ...privateOptionalX };
let sn: number = o2.x; // error, x is private
let optionalString: { sn?: string };
let optionalNumber: { sn?: number };
@ -18,30 +20,27 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe
// assignability as target
interface Bool { b: boolean };
interface Str { s: string };
let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b'
let b: Bool;
let spread = { ...{ b: true }, ...{s: "foo" } };
spread = { s: "foo" }; // error, missing 'b'
let b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
let duplicatedSpread = { ...o, ...o }
// null and undefined are just skipped
let spreadNull = { ...null }
spreadNull.null;
let spreadUndefined = { ...undefined }
spreadUndefined.undefined;
// primitives and functions are skipped
// null, undefined and primitives are not allowed
let spreadNull = { ...null };
let spreadUndefind = { ...undefined };
let spreadNum = { ...12 };
spreadNum.toFixed(); // error, no methods from number
let spreadSum = { ...1 + 1 };
spreadSum.toFixed(); // error, no methods from number
let spreadBool = { ...false };
spreadBool.valueOf(); // error, what were you thinking?
let spreadStr = { ...'foo' };
spreadStr.length; // error, no 'length'
spreadStr.charAt(1); // error, no methods either
let spreadBool = { ...true };
spreadBool.valueOf(); // error, what were you thinking?
// functions are skipped
let spreadFunc = { ...function () { } }
spreadFunc(); // error, no call signature
@ -55,17 +54,21 @@ let c: C = new C()
let spreadC = { ...c }
spreadC.m(); // error 'm' is not in '{ ... c }'
let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) };
callableConstructableSpread(12); // error, no call signature
new callableConstructableSpread(12); // error, no construct signature
function override<T,U,V>(initial: U, override: U, t: T, v: V): U {
// { ... T & V } is not assignable to { ... T & U }
let tvs: { ...T & V };
let mistake: { ...T & U } = tvs;
// { ...U } is not assignable to U
// generics
function f<T, U>(t: T, u: U) {
return { ...t, ...u, id: 'id' };
}
function override<U>(initial: U, override: U): U {
return { ...initial, ...override };
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
let overlap: { id: string, a: number, b: string } =
f({ a: 1 }, { a: 2, b: 'extra' })
let overlapConflict: { id:string, a: string } =
f({ a: 1 }, { a: 'mismatch' })
let overwriteId: { id: string, a: number, c: number, d: string } =
f({ a: 1, id: true }, { c: 1, d: 'no' })
//// [objectSpreadNegative.js]
@ -89,34 +92,34 @@ var PublicX = (function () {
}
return PublicX;
}());
var o2;
var publicX;
var privateOptionalX;
var o2 = __assign({}, publicX, privateOptionalX);
var sn = o2.x; // error, x is private
var optionalString;
var optionalNumber;
var allOptional = __assign({}, optionalString, optionalNumber);
;
;
var spread = { s: 'foo' }; // error, missing 'b'
var b;
var spread = __assign({ b: true }, { s: "foo" });
spread = { s: "foo" }; // error, missing 'b'
var b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
var duplicated = __assign({ b: 'bad' }, o, { b: 'bad' }, o2, { b: 'bad' });
var duplicatedSpread = __assign({}, o, o);
// null and undefined are just skipped
// null, undefined and primitives are not allowed
var spreadNull = __assign({}, null);
spreadNull.null;
var spreadUndefined = __assign({}, undefined);
spreadUndefined.undefined;
// primitives and functions are skipped
var spreadUndefind = __assign({}, undefined);
var spreadNum = __assign({}, 12);
spreadNum.toFixed(); // error, no methods from number
var spreadSum = __assign({}, 1 + 1);
spreadSum.toFixed(); // error, no methods from number
var spreadBool = __assign({}, false);
spreadBool.valueOf(); // error, what were you thinking?
var spreadStr = __assign({}, 'foo');
spreadStr.length; // error, no 'length'
spreadStr.charAt(1); // error, no methods either
var spreadBool = __assign({}, true);
spreadBool.valueOf(); // error, what were you thinking?
// functions are skipped
var spreadFunc = __assign({}, function () { });
spreadFunc(); // error, no call signature
// write-only properties get skipped
@ -133,13 +136,14 @@ var C = (function () {
var c = new C();
var spreadC = __assign({}, c);
spreadC.m(); // error 'm' is not in '{ ... c }'
var callableConstructableSpread;
callableConstructableSpread(12); // error, no call signature
new callableConstructableSpread(12); // error, no construct signature
function override(initial, override, t, v) {
// { ... T & V } is not assignable to { ... T & U }
var tvs;
var mistake = tvs;
// { ...U } is not assignable to U
// generics
function f(t, u) {
return __assign({}, t, u, { id: 'id' });
}
function override(initial, override) {
return __assign({}, initial, override);
}
var exclusive = f({ a: 1, b: 'yes' }, { c: 'no', d: false });
var overlap = f({ a: 1 }, { a: 2, b: 'extra' });
var overlapConflict = f({ a: 1 }, { a: 'mismatch' });
var overwriteId = f({ a: 1, id: true }, { c: 1, d: 'no' });

View File

@ -1,26 +1,36 @@
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,12): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,15): error TS2304: Cannot find name 'o'.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,18): error TS1109: Expression expected.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,12): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,15): error TS1109: Expression expected.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,16): error TS2304: Cannot find name 'o'.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,12): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,15): error TS2304: Cannot find name 'matchMedia'.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,28): error TS1005: ',' expected.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,31): error TS1128: Declaration or statement expected.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,13): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,16): error TS2304: Cannot find name 'get'.
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error TS1005: ',' expected.
==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (9 errors) ====
==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (13 errors) ====
let o7 = { ...o? };
~~~~~
!!! error TS2698: Spread types may only be created from object types.
~
!!! error TS2304: Cannot find name 'o'.
~
!!! error TS1109: Expression expected.
let o8 = { ...*o };
~~~~~
!!! error TS2698: Spread types may only be created from object types.
~
!!! error TS1109: Expression expected.
~
!!! error TS2304: Cannot find name 'o'.
let o9 = { ...matchMedia() { }};
~~~~~~~~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
~~~~~~~~~~
!!! error TS2304: Cannot find name 'matchMedia'.
~
@ -28,6 +38,8 @@ tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error T
~
!!! error TS1128: Declaration or statement expected.
let o10 = { ...get x() { return 12; }};
~~~~~~
!!! error TS2698: Spread types may only be created from object types.
~~~
!!! error TS2304: Cannot find name 'get'.
~

View File

@ -1,8 +0,0 @@
interface Congealed<T, U> {
...T
...U
}
let sandwich: Congealed<{jam: number }, { peanutButter: number }>;
sandwich.jam;
sandwich.peanutButter;

View File

@ -35,13 +35,8 @@ let getter: { a: number, c: number } =
{ ...op, c: 7 }
getter.a = 12;
// null, undefined, functions and primitives result in { }
let spreadNull = { ...null };
let spreadUndefind = { ...undefined };
let spreadNum = { ...12 };
let spreadBool = { ...false };
// functions result in { }
let spreadFunc = { ...(function () { }) };
let spreadStr = { ...'foo' };
// methods are not enumerable
class C { p = 1; m() { } }
@ -80,19 +75,3 @@ let computedAfter: { a: number, b: string, "at the end": number } =
let a = 12;
let shortCutted: { a: number, b: string } = { ...o, a }
// generics
function f<T, U>(t: T, u: U): { ...T, ...U, id: string } {
return { ...t, ...u, id: 'id' };
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
let overlap: { id: string, a: number, b: string } =
f({ a: 1 }, { a: 2, b: 'extra' })
let overlapConflict: { id:string, a: string } =
f({ a: 1 }, { a: 'mismatch' })
let overwriteId: { id: string, a: number, c: number, d: string } =
f({ a: 1, id: true }, { c: 1, d: 'no' })
class D { m() { }; q = 2; }
let classesAreWrong: { id: string, ...C, ...D } =
f(new C(), new D())

View File

@ -1,72 +0,0 @@
function f<T, U, V>(t: T, u: U, v: V): void {
let o: { ...T, ...U, ...V };
let uus: { ...U, ...U};
let us: { ...U };
const same: { ...T, ...U, ...V } = o; // ok
uus = us; // ok, multiple spreads are equivalent to a single one
us = uus; // ok, multiple spreads are equivalent to a single one
us = u; // ok, type has at least all the properties of the spread
u = us; // error, might be missing a ton of stuff
const reversed: { ...V, ...U, ...T } = o; // error, reversed
const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed
const missingT: { ...U, ...V } = o; // error, missing T
const missingU: { ...T, ...V } = o; // error, missing U
const missingV: { ...T, ...U } = o; // error, missing V
const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok
const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable
const emptyTarget: { } = { ...t, ...u } // ok
const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T)
// error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to
// T ... { sn?: number | string | boolean }
let optionalNumber: { sn?: number };
let optionalString: { sn?: string };
let optionalBoolean: { sn?: boolean };
const unionCutoff: { ...T, sn?: number | string | boolean } =
{ ...optionalBoolean, ...t, ...optionalString, ...optionalNumber }
unionCutoff.sn; // ok
const optionalCutoff = { ...t, ...optionalNumber }; // ok
optionalCutoff.sn; // ok
const interspersed: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const interspersedMissingU: { first: string, second: string, ...T, third: string } =
{ first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing
const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } =
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } =
{ first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable
const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } =
{ firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable
const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable
const mismatchLast: { first: string, ...T, second: string, ...U, third: string } =
{ first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable
}
function indexAccessedTest<T, K extends keyof T, U, J extends keyof U>(t: T, u: U, key1: K, key2: J) {
let k1: { ...keyof T };
let k2: { ...keyof U };
let k3: { ...K };
let k4: { ...J };
k1 = k1; // ok
k2 = k2; // ok
k1 = k2; // error
k2 = k1; // error
k3 = k3; // ok
k4 = k4; // ok
k1 = k3; // error
k3 = k1; // error
k2 = k4; // error
k4 = k2; // error
let i1: { ...T[K] };
let i2: { ...U[J] };
i1 = i1; // ok
i2 = i2; // ok
i1 = i2; // error
i2 = i1; // error
}

View File

@ -1,25 +1,16 @@
class C {
a: number;
c: boolean;
}
// index signatures are not allowed in object literals with spread types
let c: { ...C, b: string, c?: string, [n: number]: string };
let n: number = c.a;
let s: string = c[12];
interface Indexed {
[n: string]: number;
a: number;
}
let i: { ...Indexed, b: number };
n = i[101];
n = i.b;
interface Indexed2 {
[n: string]: boolean;
c: boolean;
}
let ii: { ...Indexed, ...Indexed2, b: boolean, d: number };
let nb: number | boolean = ii[1001];
function f<T>(t: T) {
let i: { ...T, [n: number]: string };
}
let indexed: Indexed;
let indexed2: Indexed2;
let i = { ...indexed, b: 11 };
// only indexed has indexer, so i[101]: any
i[101];
let ii = { ...indexed, ...indexed2 };
// both have indexer, so i[1001]: number | boolean
ii[1001];

View File

@ -1,19 +0,0 @@
interface Result<T,U,V> {
t: T;
u: U;
v: V;
}
declare function infer<T,U,V>(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V };
declare function infer2<T,U,V>(utv: { ...U, a: V, ...T }): { t: T, u: U, v: V };
function generic<W, X, Y>(w: W, x: X, y: Y) {
// should infer { t: {}, u: {}, v: {} } because there is no trailing type parameter
return infer({ ...w, ...x, a: y, b: "different type" });
}
let b: { b: number };
let c: { c: number };
// can only infer { t: {}, u: {}, v: {} }
let i1 = infer({ ...b, ...c, a: 12 });
// can only infer { t: {}, u: {}, v: {} }
let i2 = infer2({ ...b, ...c, a: 12 });
// can only infer { t: {}, u: {}, v: {} }
let i3 = generic(b, c, { a: 12 });

View File

@ -1,36 +0,0 @@
function iteratedUnionIntersection<T, U, V>(t: T, u: U, v: V): void {
let tu: T | U;
let uv: U & V;
let result = { ...tu, ...uv, id: 'foo' };
let assignable: { ...(T | U), ...(U & V), id: string } = result;
}
// concrete types work
interface A1 { a: number }
interface A2 { a: string }
interface B1 { b: number }
interface B2 { b: string }
let a12: A1 & A2;
let b12: B1 & B2;
let result = { ...a12, ...b12 };
let sn: number & string = result.a;
sn = result.b;
let assignable: { ...(A1 & A2), ...(B1 & B2) } = result;
function tripleIntersection<T, U, V>(t: T, u: U, v: V): void {
let tuv: T & U & V;
let result = { ...tuv, id: 'bar' };
let assignable: { ...(T & U & V), id: string } = result;
}
function iteratedDoubleIntersection<T, U, V>(t: T, u: U, v: V): void {
let tu: T & U;
let uv: U & V;
let result = { ...tu, ...uv, id: 'baz' };
let assignable: { ...(T & U), ...(U & V), id: string } = result;
}
function iteratedIntersectionUnion<T, U, V>(t: T, u: U, v: V): void {
let tu: T & U;
let uv: U | V;
let result = { ...tu, ...uv, id: 'qux' };
let assignable: { ...(T & U), ...(U | V), id: string } = result;
}

View File

@ -8,7 +8,9 @@ class PrivateOptionalX {
class PublicX {
public x: number;
}
let o2: { ...PublicX, ...PrivateOptionalX };
let publicX: PublicX;
let privateOptionalX: PrivateOptionalX;
let o2 = { ...publicX, ...privateOptionalX };
let sn: number = o2.x; // error, x is private
let optionalString: { sn?: string };
let optionalNumber: { sn?: number };
@ -18,30 +20,27 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe
// assignability as target
interface Bool { b: boolean };
interface Str { s: string };
let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b'
let b: Bool;
let spread = { ...{ b: true }, ...{s: "foo" } };
spread = { s: "foo" }; // error, missing 'b'
let b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
let duplicatedSpread = { ...o, ...o }
// null and undefined are just skipped
let spreadNull = { ...null }
spreadNull.null;
let spreadUndefined = { ...undefined }
spreadUndefined.undefined;
// primitives and functions are skipped
// null, undefined and primitives are not allowed
let spreadNull = { ...null };
let spreadUndefind = { ...undefined };
let spreadNum = { ...12 };
spreadNum.toFixed(); // error, no methods from number
let spreadSum = { ...1 + 1 };
spreadSum.toFixed(); // error, no methods from number
let spreadBool = { ...false };
spreadBool.valueOf(); // error, what were you thinking?
let spreadStr = { ...'foo' };
spreadStr.length; // error, no 'length'
spreadStr.charAt(1); // error, no methods either
let spreadBool = { ...true };
spreadBool.valueOf(); // error, what were you thinking?
// functions are skipped
let spreadFunc = { ...function () { } }
spreadFunc(); // error, no call signature
@ -55,14 +54,18 @@ let c: C = new C()
let spreadC = { ...c }
spreadC.m(); // error 'm' is not in '{ ... c }'
let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) };
callableConstructableSpread(12); // error, no call signature
new callableConstructableSpread(12); // error, no construct signature
function override<T,U,V>(initial: U, override: U, t: T, v: V): U {
// { ... T & V } is not assignable to { ... T & U }
let tvs: { ...T & V };
let mistake: { ...T & U } = tvs;
// { ...U } is not assignable to U
// generics
function f<T, U>(t: T, u: U) {
return { ...t, ...u, id: 'id' };
}
function override<U>(initial: U, override: U): U {
return { ...initial, ...override };
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
let overlap: { id: string, a: number, b: string } =
f({ a: 1 }, { a: 2, b: 'extra' })
let overlapConflict: { id:string, a: string } =
f({ a: 1 }, { a: 'mismatch' })
let overwriteId: { id: string, a: number, c: number, d: string } =
f({ a: 1, id: true }, { c: 1, d: 'no' })

View File

@ -1,17 +0,0 @@
interface A1 { a: boolean }
interface B1 { b: number };
function override<U>(initial: U, override: U): { ...U, ...U } {
return { ...initial, ...override };
}
function update<U>(this: { u: { ...U } }, override: U): void {
this.u = { ...this.u, ...override };
}
function mixin<T, U>(one: T, two: U): { ...T, ...U } {
return { ...one, ...two };
}
let a1: A1 = { a: true };
let b1: B1 = { b: 101 };
a1 = override(a1, { a: false });
let host = { u: a1, update };
host.update({ a: false });
let mixed = mixin(a1, b1);

View File

@ -1,23 +0,0 @@
// concrete types work
interface A1 { a: number }
interface A2 { a: string }
let a12: A1 | A2;
let result = { ...a12 };
let sn: number | string = result.a;
let assignable: { ...(A1 | A2) } = result;
function tripleUnion<T, U, V>(t: T, u: U, v: V): void {
let tuv: T | U | V;
let result = { ...tuv, id: 'foo' };
let expected: { ...T, id: string } | { ...U, id: string } | { ...V, id: string } = result;
let assignable: { ...(T | U | V), id: string } = result;
}
function iteratedDoubleUnion<T, U, V>(t: T, u: U, v: V): void {
let tu: T | U;
let uv: U | V;
let result = { ...tu, ...uv, id: 'bar' };
let expected: { ...T, ...U, id: string } | { ...T, ...V, id: string } | { ...U, id: string } | { ...U, ...V, id: string };
let assignable: { ...(T | U), ...(U | V), id: string } = result;
}

View File

@ -2,7 +2,9 @@
////interface A1 { [|a|]: string };
////interface A2 { [|a|]?: number };
////let a12: { ...A1, ...A2 };
////let a1: A1;
////let a2: A2;
////let a12 = { ...a1, ...a2 };
////a12.[|a|];
const ranges = test.ranges();
// members of spread types only refer to themselves and the resulting property

View File

@ -2,6 +2,8 @@
////interface A1 { /*1*/a: number };
////interface A2 { /*2*/a?: number };
////let a12: { ...A1, ...A2 };
////let a1: A1;
////let a2: A2;
////let a12 = { ...a1, ...a2 };
////a12.a/*3*/;
verify.goToDefinition('3', [ '1', '2' ]);

View File

@ -2,7 +2,9 @@
////interface A1 { [|a|]: number };
////interface A2 { [|a|]?: number };
////let a12: { ...A1, ...A2 };
////let a1: A1;
////let a2: A2;
////let a12 = { ...a1, ...a2 };
////a12.[|a|];
const ranges = test.ranges();
verify.assertHasRanges(ranges);