Merge pull request #12114 from Microsoft/mappedTypes

Mapped types
This commit is contained in:
Anders Hejlsberg 2016-11-13 15:39:32 -08:00 committed by GitHub
commit f437c8f318
33 changed files with 2757 additions and 171 deletions

View file

@ -1308,6 +1308,7 @@ namespace ts {
case SyntaxKind.JSDocFunctionType:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.MappedType:
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
case SyntaxKind.SourceFile:
@ -1427,6 +1428,7 @@ namespace ts {
case SyntaxKind.ArrowFunction:
case SyntaxKind.JSDocFunctionType:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.MappedType:
// All the children of these container types are never visible through another
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
// they're only accessed 'lexically' (i.e. from code that exists underneath
@ -1977,9 +1979,10 @@ namespace ts {
case SyntaxKind.JSDocFunctionType:
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
case SyntaxKind.TypeLiteral:
case SyntaxKind.MappedType:
case SyntaxKind.JSDocTypeLiteral:
case SyntaxKind.JSDocRecordType:
return bindAnonymousDeclaration(<TypeLiteralNode>node, SymbolFlags.TypeLiteral, "__type");
return bindAnonymousDeclaration(<Declaration>node, SymbolFlags.TypeLiteral, "__type");
case SyntaxKind.ObjectLiteralExpression:
return bindObjectLiteralExpression(<ObjectLiteralExpression>node);
case SyntaxKind.FunctionExpression:
@ -3153,6 +3156,7 @@ namespace ts {
case SyntaxKind.ThisType:
case SyntaxKind.TypeOperator:
case SyntaxKind.IndexedAccessType:
case SyntaxKind.MappedType:
case SyntaxKind.LiteralType:
// Types and signatures are TypeScript syntax, and exclude all other facts.
transformFlags = TransformFlags.AssertTypeScript;

View file

@ -2248,7 +2248,7 @@ namespace ts {
// The specified symbol flags need to be reinterpreted as type flags
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
}
else if (!(flags & TypeFormatFlags.InTypeAlias) && (getObjectFlags(type) & ObjectFlags.Anonymous || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol &&
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
const typeArguments = type.aliasTypeArguments;
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
@ -2256,7 +2256,7 @@ namespace ts {
else if (type.flags & TypeFlags.UnionOrIntersection) {
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
}
else if (getObjectFlags(type) & ObjectFlags.Anonymous) {
else if (getObjectFlags(type) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
writeAnonymousType(<ObjectType>type, nextFlags);
}
else if (type.flags & TypeFlags.StringOrNumberLiteral) {
@ -2475,6 +2475,13 @@ namespace ts {
}
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
if (type.objectFlags & ObjectFlags.Mapped) {
if (getConstraintTypeFromMappedType(<MappedType>type).flags & (TypeFlags.TypeParameter | TypeFlags.Index)) {
writeMappedType(<MappedType>type);
return;
}
}
const resolved = resolveStructuredTypeMembers(type);
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
@ -2553,7 +2560,34 @@ namespace ts {
}
}
}
}
function writeMappedType(type: MappedType) {
writePunctuation(writer, SyntaxKind.OpenBraceToken);
writer.writeLine();
writer.increaseIndent();
if (type.declaration.readonlyToken) {
writeKeyword(writer, SyntaxKind.ReadonlyKeyword);
writeSpace(writer);
}
writePunctuation(writer, SyntaxKind.OpenBracketToken);
appendSymbolNameOnly(getTypeParameterFromMappedType(type).symbol, writer);
writeSpace(writer);
writeKeyword(writer, SyntaxKind.InKeyword);
writeSpace(writer);
writeType(getConstraintTypeFromMappedType(type), TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
if (type.declaration.questionToken) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
writeType(getTemplateTypeFromMappedType(type), TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
writer.decreaseIndent();
writePunctuation(writer, SyntaxKind.CloseBraceToken);
}
}
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags) {
const targetSymbol = getTargetSymbol(symbol);
@ -3694,7 +3728,7 @@ namespace ts {
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] {
let signatures = getConstructorsForTypeArguments(type, typeArgumentNodes);
if (typeArgumentNodes) {
const typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias);
const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
signatures = map(signatures, sig => getSignatureInstantiation(sig, typeArguments));
}
return signatures;
@ -3905,7 +3939,6 @@ namespace ts {
return unknownType;
}
const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
let declaration: JSDocTypedefTag | TypeAliasDeclaration = <JSDocTypedefTag>getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag);
let type: Type;
if (declaration) {
@ -3918,16 +3951,17 @@ namespace ts {
}
else {
declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
type = getTypeFromTypeNode(declaration.type, symbol, typeParameters);
type = getTypeFromTypeNode(declaration.type);
}
if (popTypeResolution()) {
links.typeParameters = typeParameters;
const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
if (typeParameters) {
// Initialize the instantiation cache for generic type aliases. The declared type corresponds to
// an instantiation of the type alias with the type parameters supplied as type arguments.
links.typeParameters = typeParameters;
links.instantiations = createMap<Type>();
links.instantiations[getTypeListId(links.typeParameters)] = type;
links.instantiations[getTypeListId(typeParameters)] = type;
}
}
else {
@ -4263,7 +4297,7 @@ namespace ts {
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNodeNoAlias);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
const result: Signature[] = [];
for (const baseSig of baseSignatures) {
@ -4450,6 +4484,80 @@ namespace ts {
}
}
/** Resolve the members of a mapped type { [P in K]: T } */
function resolveMappedTypeMembers(type: MappedType) {
const members: SymbolTable = createMap<Symbol>();
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
// In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
// and T as the template type.
const typeParameter = getTypeParameterFromMappedType(type);
const constraintType = getConstraintTypeFromMappedType(type);
const templateType = getTemplateTypeFromMappedType(type);
const isReadonly = !!type.declaration.readonlyToken;
const isOptional = !!type.declaration.questionToken;
// First, if the constraint type is a type parameter, obtain the base constraint. Then,
// if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
// Finally, iterate over the constituents of the resulting iteration type.
const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentType(constraintType) : constraintType;
const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType;
forEachType(iterationType, t => {
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
const iterationMapper = createUnaryTypeMapper(typeParameter, t);
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, iterationMapper) : iterationMapper;
const propType = instantiateType(templateType, templateMapper);
// If the current iteration type constituent is a literal type, create a property.
// Otherwise, for type string create a string index signature and for type number
// create a numeric index signature.
if (t.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) {
const propName = (<LiteralType>t).text;
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
prop.type = addOptionality(propType, isOptional);
prop.isReadonly = isReadonly;
members[propName] = prop;
}
else if (t.flags & TypeFlags.String) {
stringIndexInfo = createIndexInfo(propType, isReadonly);
}
else if (t.flags & TypeFlags.Number) {
numberIndexInfo = createIndexInfo(propType, isReadonly);
}
});
// If we created both a string and a numeric string index signature, and if the two index
// signatures have identical types, discard the redundant numeric index signature.
if (stringIndexInfo && numberIndexInfo && isTypeIdenticalTo(stringIndexInfo.type, numberIndexInfo.type)) {
numberIndexInfo = undefined;
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
function getTypeParameterFromMappedType(type: MappedType) {
return type.typeParameter ||
(type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter)));
}
function getConstraintTypeFromMappedType(type: MappedType) {
return type.constraintType ||
(type.constraintType = instantiateType(getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)), type.mapper || identityMapper) || unknownType);
}
function getTemplateTypeFromMappedType(type: MappedType) {
return type.templateType ||
(type.templateType = type.declaration.type ?
instantiateType(getTypeFromTypeNode(type.declaration.type), type.mapper || identityMapper) :
unknownType);
}
function isGenericMappedType(type: Type) {
if (getObjectFlags(type) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
return !!(constraintType.flags & (TypeFlags.TypeParameter | TypeFlags.Index));
}
return false;
}
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
if (!(<ResolvedType>type).members) {
if (type.flags & TypeFlags.Object) {
@ -4462,6 +4570,9 @@ namespace ts {
else if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
resolveAnonymousTypeMembers(<AnonymousType>type);
}
else if ((<MappedType>type).objectFlags & ObjectFlags.Mapped) {
resolveMappedTypeMembers(<MappedType>type);
}
}
else if (type.flags & TypeFlags.Union) {
resolveUnionTypeMembers(<UnionType>type);
@ -5212,7 +5323,7 @@ namespace ts {
// In a type reference, the outer type parameters of the referenced class or interface are automatically
// supplied as type arguments and the type reference only specifies arguments for the local type parameters
// of the class or interface.
return createTypeReference(<GenericType>type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNodeNoAlias)));
return createTypeReference(<GenericType>type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNode)));
}
if (node.typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
@ -5221,21 +5332,27 @@ namespace ts {
return type;
}
function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[]): Type {
const type = getDeclaredTypeOfSymbol(symbol);
const links = getSymbolLinks(symbol);
const typeParameters = links.typeParameters;
const id = getTypeListId(typeArguments);
return links.instantiations[id] || (links.instantiations[id] = instantiateTypeNoAlias(type, createTypeMapper(typeParameters, typeArguments)));
}
// Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
// references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
// declared type. Instantiations are cached using the type identities of the type arguments as the key.
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
const type = getDeclaredTypeOfSymbol(symbol);
const links = getSymbolLinks(symbol);
const typeParameters = links.typeParameters;
const typeParameters = getSymbolLinks(symbol).typeParameters;
if (typeParameters) {
if (!node.typeArguments || node.typeArguments.length !== typeParameters.length) {
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, symbolToString(symbol), typeParameters.length);
return unknownType;
}
const typeArguments = map(node.typeArguments, getTypeFromTypeNodeNoAlias);
const id = getTypeListId(typeArguments);
return links.instantiations[id] || (links.instantiations[id] = instantiateType(type, createTypeMapper(typeParameters, typeArguments)));
const typeArguments = map(node.typeArguments, getTypeFromTypeNode);
return getTypeAliasInstantiation(symbol, typeArguments);
}
if (node.typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, symbolToString(symbol));
@ -5486,7 +5603,7 @@ namespace ts {
function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNodeNoAlias));
links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode));
}
return links.resolvedType;
}
@ -5676,10 +5793,11 @@ namespace ts {
return type;
}
function getTypeFromUnionTypeNode(node: UnionTypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNodeNoAlias), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*subtypeReduction*/ false,
getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
}
return links.resolvedType;
}
@ -5747,10 +5865,11 @@ namespace ts {
return type;
}
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNodeNoAlias), aliasSymbol, aliasTypeArguments);
links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode),
getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
}
return links.resolvedType;
}
@ -5764,7 +5883,9 @@ namespace ts {
}
function getLiteralTypeFromPropertyName(prop: Symbol) {
return startsWith(prop.name, "__@") ? neverType : getLiteralTypeForText(TypeFlags.StringLiteral, unescapeIdentifier(prop.name));
return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.name, "__@") ?
neverType :
getLiteralTypeForText(TypeFlags.StringLiteral, unescapeIdentifier(prop.name));
}
function getLiteralTypeFromPropertyNames(type: Type) {
@ -5781,7 +5902,7 @@ namespace ts {
function getTypeFromTypeOperatorNode(node: TypeOperatorNode) {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getIndexType(getTypeFromTypeNodeNoAlias(node.type));
links.resolvedType = getIndexType(getTypeFromTypeNode(node.type));
}
return links.resolvedType;
}
@ -5863,10 +5984,8 @@ namespace ts {
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
if (indexType.flags & TypeFlags.TypeParameter) {
if (!isTypeAssignableTo(getConstraintOfTypeParameter(<TypeParameter>indexType) || emptyObjectType, getIndexType(objectType))) {
if (accessNode) {
error(accessNode, Diagnostics.Type_0_is_not_constrained_to_keyof_1, typeToString(indexType), typeToString(objectType));
}
if (accessNode && !isTypeAssignableTo(getConstraintOfTypeParameter(<TypeParameter>indexType) || emptyObjectType, getIndexType(objectType))) {
error(accessNode, Diagnostics.Type_0_is_not_constrained_to_keyof_1, typeToString(indexType), typeToString(objectType));
return unknownType;
}
return getIndexedAccessTypeForTypeParameter(objectType, <TypeParameter>indexType);
@ -5889,28 +6008,50 @@ namespace ts {
function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getIndexedAccessType(getTypeFromTypeNodeNoAlias(node.objectType), getTypeFromTypeNodeNoAlias(node.indexType), node);
links.resolvedType = getIndexedAccessType(getTypeFromTypeNode(node.objectType), getTypeFromTypeNode(node.indexType), node);
}
return links.resolvedType;
}
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
function getTypeFromMappedTypeNode(node: MappedTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const type = <MappedType>createObjectType(ObjectFlags.Mapped, node.symbol);
type.declaration = node;
type.aliasSymbol = getAliasSymbolForTypeNode(node);
type.aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
links.resolvedType = type;
}
return links.resolvedType;
}
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
// Deferred resolution of members is handled by resolveObjectTypeMembers
if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) {
const aliasSymbol = getAliasSymbolForTypeNode(node);
if (isEmpty(node.symbol.members) && !aliasSymbol) {
links.resolvedType = emptyTypeLiteralType;
}
else {
const type = createObjectType(ObjectFlags.Anonymous, node.symbol);
type.aliasSymbol = aliasSymbol;
type.aliasTypeArguments = aliasTypeArguments;
type.aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
links.resolvedType = type;
}
}
return links.resolvedType;
}
function getAliasSymbolForTypeNode(node: TypeNode) {
return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined;
}
function getAliasTypeArgumentsForTypeNode(node: TypeNode) {
const symbol = getAliasSymbolForTypeNode(node);
return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined;
}
/**
* Since the source of spread types are object literals, which are not binary,
* this function should be called in a left folding style, with left = previous result of getSpreadType
@ -6020,7 +6161,7 @@ namespace ts {
function getTypeFromJSDocTupleType(node: JSDocTupleType): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const types = map(node.types, getTypeFromTypeNodeNoAlias);
const types = map(node.types, getTypeFromTypeNode);
links.resolvedType = createTupleType(types);
}
return links.resolvedType;
@ -6047,11 +6188,7 @@ namespace ts {
return links.resolvedType;
}
function getTypeFromTypeNodeNoAlias(type: TypeNode) {
return getTypeFromTypeNode(type, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined);
}
function getTypeFromTypeNode(node: TypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
function getTypeFromTypeNode(node: TypeNode): Type {
switch (node.kind) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.JSDocAllType:
@ -6102,9 +6239,9 @@ namespace ts {
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
case SyntaxKind.UnionType:
case SyntaxKind.JSDocUnionType:
return getTypeFromUnionTypeNode(<UnionTypeNode>node, aliasSymbol, aliasTypeArguments);
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
case SyntaxKind.IntersectionType:
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node, aliasSymbol, aliasTypeArguments);
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node);
case SyntaxKind.ParenthesizedType:
case SyntaxKind.JSDocNullableType:
case SyntaxKind.JSDocNonNullableType:
@ -6119,11 +6256,13 @@ namespace ts {
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocTypeLiteral:
case SyntaxKind.JSDocFunctionType:
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments);
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
case SyntaxKind.TypeOperator:
return getTypeFromTypeOperatorNode(<TypeOperatorNode>node);
case SyntaxKind.IndexedAccessType:
return getTypeFromIndexedAccessTypeNode(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return getTypeFromMappedTypeNode(<MappedTypeNode>node);
// This function assumes that an identifier or qualified name is a type expression
// Callers should first ensure this by calling isTypeNode
case SyntaxKind.Identifier:
@ -6158,6 +6297,11 @@ namespace ts {
return instantiateList(signatures, mapper, instantiateSignature);
}
function instantiateCached<T extends Type>(type: T, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T {
const instantiations = mapper.instantiations || (mapper.instantiations = []);
return <T>instantiations[type.id] || (instantiations[type.id] = instantiator(type, mapper));
}
function createUnaryTypeMapper(source: Type, target: Type): TypeMapper {
return t => t === source ? target : t;
}
@ -6295,23 +6439,21 @@ namespace ts {
return result;
}
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): ObjectType {
if (mapper.instantiations) {
const cachedType = <ObjectType>mapper.instantiations[type.id];
if (cachedType) {
return cachedType;
}
}
else {
mapper.instantiations = [];
}
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType {
const result = <AnonymousType>createObjectType(ObjectFlags.Anonymous | ObjectFlags.Instantiated, type.symbol);
result.target = type;
result.mapper = mapper;
result.target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type;
result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
result.aliasSymbol = type.aliasSymbol;
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
return result;
}
function instantiateMappedType(type: MappedType, mapper: TypeMapper): MappedType {
const result = <MappedType>createObjectType(ObjectFlags.Mapped | ObjectFlags.Instantiated, type.symbol);
result.declaration = type.declaration;
result.mapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
result.aliasSymbol = type.aliasSymbol;
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
mapper.instantiations[type.id] = result;
return result;
}
@ -6367,41 +6509,80 @@ namespace ts {
return false;
}
function isTopLevelTypeAlias(symbol: Symbol) {
if (symbol.declarations && symbol.declarations.length) {
const parentKind = symbol.declarations[0].parent.kind;
return parentKind === SyntaxKind.SourceFile || parentKind === SyntaxKind.ModuleBlock;
}
return false;
}
function instantiateType(type: Type, mapper: TypeMapper): Type {
if (type && mapper !== identityMapper) {
if (type.flags & TypeFlags.TypeParameter) {
return mapper(<TypeParameter>type);
}
if (type.flags & TypeFlags.Object) {
if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
// If the anonymous type originates in a declaration of a function, method, class, or
// interface, in an object type literal, or in an object literal expression, we may need
// to instantiate the type because it might reference a type parameter. We skip instantiation
// if none of the type parameters that are in scope in the type's declaration are mapped by
// the given mapper, however we can only do that analysis if the type isn't itself an
// instantiation.
return type.symbol &&
type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
((<ObjectType>type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
instantiateAnonymousType(<AnonymousType>type, mapper) : type;
}
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
// If we are instantiating a type that has a top-level type alias, obtain the instantiation through
// the type alias instead in order to share instantiations for the same type arguments. This can
// dramatically reduce the number of structurally identical types we generate. Note that we can only
// perform this optimization for top-level type aliases. Consider:
//
// function f1<T>(x: T) {
// type Foo<X> = { x: X, t: T };
// let obj: Foo<T> = { x: x };
// return obj;
// }
// function f2<U>(x: U) { return f1(x); }
// let z = f2(42);
//
// Above, the declaration of f2 has an inferred return type that is an instantiation of f1's Foo<X>
// equivalent to { x: U, t: U }. When instantiating this return type, we can't go back to Foo<X>'s
// cache because all cached instantiations are of the form { x: ???, t: T }, i.e. they have not been
// instantiated for T. Instead, we need to further instantiate the { x: U, t: U } form.
if (type.aliasSymbol && isTopLevelTypeAlias(type.aliasSymbol)) {
if (type.aliasTypeArguments) {
return getTypeAliasInstantiation(type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
return type;
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
return instantiateTypeNoAlias(type, mapper);
}
return type;
}
function instantiateTypeNoAlias(type: Type, mapper: TypeMapper): Type {
if (type.flags & TypeFlags.TypeParameter) {
return mapper(<TypeParameter>type);
}
if (type.flags & TypeFlags.Object) {
if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
// If the anonymous type originates in a declaration of a function, method, class, or
// interface, in an object type literal, or in an object literal expression, we may need
// to instantiate the type because it might reference a type parameter. We skip instantiation
// if none of the type parameters that are in scope in the type's declaration are mapped by
// the given mapper, however we can only do that analysis if the type isn't itself an
// instantiation.
return type.symbol &&
type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
((<ObjectType>type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
instantiateCached(type, mapper, instantiateAnonymousType) : type;
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
if ((<ObjectType>type).objectFlags & ObjectFlags.Mapped) {
return instantiateCached(type, mapper, instantiateMappedType);
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));
}
if (type.flags & TypeFlags.IndexedAccess) {
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
}
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));
}
if (type.flags & TypeFlags.IndexedAccess) {
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
}
return type;
}
@ -6890,6 +7071,13 @@ namespace ts {
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
if (source.flags & TypeFlags.Index) {
// A keyof T is related to a union type containing both string and number
if (maybeTypeOfKind(target, TypeFlags.String) && maybeTypeOfKind(target, TypeFlags.Number)) {
return Ternary.True;
}
}
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
if (reportErrors) {
@ -6962,6 +7150,12 @@ namespace ts {
}
}
else if (target.flags & TypeFlags.Index) {
// A keyof S is related to a keyof T if T is related to S.
if (source.flags & TypeFlags.Index) {
if (result = isRelatedTo((<IndexType>target).type, (<IndexType>source).type, /*reportErrors*/ false)) {
return result;
}
}
// Given a type parameter T with a constraint C, a type S is assignable to
// keyof T if S is assignable to keyof C.
const constraint = getConstraintOfTypeParameter((<IndexType>target).type);
@ -6996,18 +7190,29 @@ namespace ts {
return result;
}
}
// Even if relationship doesn't hold for unions, intersections, or generic type references,
// it may hold in a structural comparison.
const apparentSource = getApparentType(source);
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
// relates to X. Thus, we include intersection types on the source side here.
if (apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
// Report structural errors only if we haven't reported any errors yet
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive);
if (result = objectTypeRelatedTo(apparentSource, source, target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
if (isGenericMappedType(target)) {
// A type [P in S]: X is related to a type [P in T]: Y if T is related to S and X is related to Y.
if (isGenericMappedType(source)) {
if ((result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) &&
(result = isRelatedTo(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target), reportErrors))) {
return result;
}
}
}
else {
// Even if relationship doesn't hold for unions, intersections, or generic type references,
// it may hold in a structural comparison.
const apparentSource = getApparentType(source);
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
// relates to X. Thus, we include intersection types on the source side here.
if (apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
// Report structural errors only if we haven't reported any errors yet
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive);
if (result = objectTypeRelatedTo(apparentSource, source, target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
}
}
@ -8097,9 +8302,11 @@ namespace ts {
// we perform type inference (i.e. a type parameter of a generic function). We cache
// results for union and intersection types for performance reasons.
function couldContainTypeParameters(type: Type): boolean {
const objectFlags = getObjectFlags(type);
return !!(type.flags & TypeFlags.TypeParameter ||
getObjectFlags(type) & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
objectFlags & ObjectFlags.Mapped ||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
}
@ -8136,6 +8343,16 @@ namespace ts {
if (!couldContainTypeParameters(target)) {
return;
}
if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) {
// Source and target are types originating in the same generic type alias declaration.
// Simply infer from source type arguments to target type arguments.
const sourceTypes = source.aliasTypeArguments;
const targetTypes = target.aliasTypeArguments;
for (let i = 0; i < sourceTypes.length; i++) {
inferFromTypes(sourceTypes[i], targetTypes[i]);
}
return;
}
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
// Source and target are both unions or both intersections. If source and target
@ -8247,6 +8464,19 @@ namespace ts {
}
}
else {
if (getObjectFlags(target) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
if (getObjectFlags(source) & ObjectFlags.Mapped) {
inferFromTypes(getConstraintTypeFromMappedType(<MappedType>source), constraintType);
inferFromTypes(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
if (constraintType.flags & TypeFlags.TypeParameter) {
inferFromTypes(getIndexType(source), constraintType);
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
}
source = getApparentType(source);
if (source.flags & TypeFlags.Object) {
if (isInProcess(source, target)) {
@ -8855,6 +9085,10 @@ namespace ts {
return containsType(target.types, source);
}
function forEachType<T>(type: Type, f: (t: Type) => T): T {
return type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, f) : f(type);
}
function filterType(type: Type, f: (t: Type) => boolean): Type {
if (type.flags & TypeFlags.Union) {
const types = (<UnionType>type).types;
@ -12694,7 +12928,7 @@ namespace ts {
else if (candidateForTypeArgumentError) {
if (!isTaggedTemplate && !isDecorator && typeArguments) {
const typeArguments = (<CallExpression>node).typeArguments;
checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNodeNoAlias), /*reportErrors*/ true, headMessage);
checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNode), /*reportErrors*/ true, headMessage);
}
else {
Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
@ -12725,7 +12959,7 @@ namespace ts {
for (let candidate of candidates) {
if (hasCorrectArity(node, args, candidate)) {
if (candidate.typeParameters && typeArguments) {
candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNodeNoAlias));
candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode));
}
return candidate;
}
@ -12761,7 +12995,7 @@ namespace ts {
if (candidate.typeParameters) {
let typeArgumentTypes: Type[];
if (typeArguments) {
typeArgumentTypes = map(typeArguments, getTypeFromTypeNodeNoAlias);
typeArgumentTypes = map(typeArguments, getTypeFromTypeNode);
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
}
else {
@ -15228,7 +15462,7 @@ namespace ts {
const constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
if (!typeArguments) {
typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias);
typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
mapper = createTypeMapper(typeParameters, typeArguments);
}
const typeArgument = typeArguments[i];
@ -15297,6 +15531,15 @@ namespace ts {
getTypeFromIndexedAccessTypeNode(node);
}
function checkMappedType(node: MappedTypeNode) {
checkSourceElement(node.typeParameter);
checkSourceElement(node.type);
const type = <MappedType>getTypeFromMappedTypeNode(node);
const constraintType = getConstraintTypeFromMappedType(type);
const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>constraintType) : constraintType;
checkTypeAssignableTo(keyType, stringOrNumberType, node.typeParameter.constraint);
}
function isPrivateWithinAmbient(node: Node): boolean {
return (getModifierFlags(node) & ModifierFlags.Private) && isInAmbientContext(node);
}
@ -18545,6 +18788,8 @@ namespace ts {
return checkSourceElement((<ParenthesizedTypeNode | TypeOperatorNode>node).type);
case SyntaxKind.IndexedAccessType:
return checkIndexedAccessType(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return checkMappedType(<MappedTypeNode>node);
case SyntaxKind.FunctionDeclaration:
return checkFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.Block:

View file

@ -416,7 +416,9 @@ namespace ts {
case SyntaxKind.TypeOperator:
return emitTypeOperator(<TypeOperatorNode>type);
case SyntaxKind.IndexedAccessType:
return emitPropertyAccessType(<IndexedAccessTypeNode>type);
return emitIndexedAccessType(<IndexedAccessTypeNode>type);
case SyntaxKind.MappedType:
return emitMappedType(<MappedTypeNode>type);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
return emitSignatureDeclarationWithJsDocComments(<FunctionOrConstructorTypeNode>type);
@ -516,13 +518,39 @@ namespace ts {
emitType(type.type);
}
function emitPropertyAccessType(node: IndexedAccessTypeNode) {
function emitIndexedAccessType(node: IndexedAccessTypeNode) {
emitType(node.objectType);
write("[");
emitType(node.indexType);
write("]");
}
function emitMappedType(node: MappedTypeNode) {
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
write("{");
writeLine();
increaseIndent();
if (node.readonlyToken) {
write("readonly ");
}
write("[");
writeEntityName(node.typeParameter.name);
write(" in ");
emitType(node.typeParameter.constraint);
write("]");
if (node.questionToken) {
write("?");
}
write(": ");
emitType(node.type);
write(";");
writeLine();
decreaseIndent();
write("}");
enclosingDeclaration = prevEnclosingDeclaration;
}
function emitTypeLiteral(type: TypeLiteralNode) {
write("{");
if (type.members.length) {

View file

@ -606,7 +606,9 @@ const _super = (function (geti, seti) {
case SyntaxKind.TypeOperator:
return emitTypeOperator(<TypeOperatorNode>node);
case SyntaxKind.IndexedAccessType:
return emitPropertyAccessType(<IndexedAccessTypeNode>node);
return emitIndexedAccessType(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return emitMappedType(<MappedTypeNode>node);
case SyntaxKind.LiteralType:
return emitLiteralType(<LiteralTypeNode>node);
@ -1109,13 +1111,36 @@ const _super = (function (geti, seti) {
emit(node.type);
}
function emitPropertyAccessType(node: IndexedAccessTypeNode) {
function emitIndexedAccessType(node: IndexedAccessTypeNode) {
emit(node.objectType);
write("[");
emit(node.indexType);
write("]");
}
function emitMappedType(node: MappedTypeNode) {
write("{");
writeLine();
increaseIndent();
if (node.readonlyToken) {
write("readonly ");
}
write("[");
emit(node.typeParameter.name);
write(" in ");
emit(node.typeParameter.constraint);
write("]");
if (node.questionToken) {
write("?");
}
write(": ");
emit(node.type);
write(";");
writeLine();
decreaseIndent();
write("}");
}
function emitLiteralType(node: LiteralTypeNode) {
emitExpression(node.literal);
}

View file

@ -141,6 +141,11 @@ namespace ts {
case SyntaxKind.IndexedAccessType:
return visitNode(cbNode, (<IndexedAccessTypeNode>node).objectType) ||
visitNode(cbNode, (<IndexedAccessTypeNode>node).indexType);
case SyntaxKind.MappedType:
return visitNode(cbNode, (<MappedTypeNode>node).readonlyToken) ||
visitNode(cbNode, (<MappedTypeNode>node).typeParameter) ||
visitNode(cbNode, (<MappedTypeNode>node).questionToken) ||
visitNode(cbNode, (<MappedTypeNode>node).type);
case SyntaxKind.LiteralType:
return visitNode(cbNode, (<LiteralTypeNode>node).literal);
case SyntaxKind.ObjectBindingPattern:
@ -2422,6 +2427,36 @@ namespace ts {
return members;
}
function isStartOfMappedType() {
nextToken();
if (token() === SyntaxKind.ReadonlyKeyword) {
nextToken();
}
return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword;
}
function parseMappedTypeParameter() {
const node = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
node.name = parseIdentifier();
parseExpected(SyntaxKind.InKeyword);
node.constraint = parseType();
return finishNode(node);
}
function parseMappedType() {
const node = <MappedTypeNode>createNode(SyntaxKind.MappedType);
parseExpected(SyntaxKind.OpenBraceToken);
node.readonlyToken = parseOptionalToken(SyntaxKind.ReadonlyKeyword);
parseExpected(SyntaxKind.OpenBracketToken);
node.typeParameter = parseMappedTypeParameter();
parseExpected(SyntaxKind.CloseBracketToken);
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
node.type = parseTypeAnnotation();
parseSemicolon();
parseExpected(SyntaxKind.CloseBraceToken);
return finishNode(node);
}
function parseTupleType(): TupleTypeNode {
const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
@ -2495,7 +2530,7 @@ namespace ts {
case SyntaxKind.TypeOfKeyword:
return parseTypeQuery();
case SyntaxKind.OpenBraceToken:
return parseTypeLiteral();
return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
case SyntaxKind.OpenBracketToken:
return parseTupleType();
case SyntaxKind.OpenParenToken:

View file

@ -302,6 +302,7 @@ namespace ts {
case SyntaxKind.ThisType:
case SyntaxKind.TypeOperator:
case SyntaxKind.IndexedAccessType:
case SyntaxKind.MappedType:
case SyntaxKind.LiteralType:
// TypeScript type nodes are elided.
@ -1791,6 +1792,7 @@ namespace ts {
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeOperator:
case SyntaxKind.IndexedAccessType:
case SyntaxKind.MappedType:
case SyntaxKind.TypeLiteral:
case SyntaxKind.AnyKeyword:
case SyntaxKind.ThisType:

View file

@ -219,6 +219,7 @@ namespace ts {
ThisType,
TypeOperator,
IndexedAccessType,
MappedType,
LiteralType,
// Binding patterns
ObjectBindingPattern,
@ -520,6 +521,7 @@ namespace ts {
export type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
export type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
export type AtToken = Token<SyntaxKind.AtToken>;
export type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
export type Modifier
= Token<SyntaxKind.AbstractKeyword>
@ -903,6 +905,14 @@ namespace ts {
indexType: TypeNode;
}
export interface MappedTypeNode extends TypeNode, Declaration {
kind: SyntaxKind.MappedType;
readonlyToken?: ReadonlyToken;
typeParameter: TypeParameterDeclaration;
questionToken?: QuestionToken;
type?: TypeNode;
}
export interface LiteralTypeNode extends TypeNode {
kind: SyntaxKind.LiteralType;
literal: Expression;
@ -2501,7 +2511,7 @@ namespace ts {
RegularEnum = 0x00000100, // Enum
ValueModule = 0x00000200, // Instantiated module
NamespaceModule = 0x00000400, // Uninstantiated module
TypeLiteral = 0x00000800, // Type Literal
TypeLiteral = 0x00000800, // Type Literal or mapped type
ObjectLiteral = 0x00001000, // Object Literal
Method = 0x00002000, // Method
Constructor = 0x00004000, // Constructor
@ -2780,10 +2790,11 @@ namespace ts {
Reference = 1 << 2, // Generic type reference
Tuple = 1 << 3, // Synthesized generic tuple type
Anonymous = 1 << 4, // Anonymous
Instantiated = 1 << 5, // Instantiated anonymous type
ObjectLiteral = 1 << 6, // Originates in an object literal
EvolvingArray = 1 << 7, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 8, // Object literal pattern with computed properties
Mapped = 1 << 5, // Mapped
Instantiated = 1 << 6, // Instantiated anonymous or mapped type
ObjectLiteral = 1 << 7, // Originates in an object literal
EvolvingArray = 1 << 8, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
ClassOrInterface = Class | Interface
}
@ -2852,6 +2863,15 @@ namespace ts {
mapper?: TypeMapper; // Instantiation mapper
}
/* @internal */
export interface MappedType extends ObjectType {
declaration: MappedTypeNode;
typeParameter?: TypeParameter;
constraintType?: Type;
templateType?: Type;
mapper?: TypeMapper; // Instantiation mapper
}
export interface EvolvingArrayType extends ObjectType {
elementType: Type; // Element expressions of evolving array type
finalArrayType?: Type; // Final array type of evolving array type

View file

@ -272,11 +272,9 @@ namespace ts.SymbolDisplay {
displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
displayParts.push(spacePart());
addFullSymbolName(symbol);
displayParts.push(spacePart());
displayParts.push(keywordPart(SyntaxKind.InKeyword));
displayParts.push(spacePart());
if (symbol.parent) {
// Class/Interface type parameter
addInPrefix();
addFullSymbolName(symbol.parent, enclosingDeclaration);
writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
}
@ -288,6 +286,7 @@ namespace ts.SymbolDisplay {
if (declaration) {
if (isFunctionLikeKind(declaration.kind)) {
addInPrefix();
const signature = typeChecker.getSignatureFromDeclaration(<SignatureDeclaration>declaration);
if (declaration.kind === SyntaxKind.ConstructSignature) {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
@ -298,10 +297,11 @@ namespace ts.SymbolDisplay {
}
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
}
else {
else if (declaration.kind === SyntaxKind.TypeAliasDeclaration) {
// Type alias type parameter
// For example
// type list<T> = T[]; // Both T will go through same code path
addInPrefix();
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(declaration.symbol);
@ -439,6 +439,12 @@ namespace ts.SymbolDisplay {
}
}
function addInPrefix() {
displayParts.push(spacePart());
displayParts.push(keywordPart(SyntaxKind.InKeyword));
displayParts.push(spacePart());
}
function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) {
const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined,
SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing);

View file

@ -1,15 +1,15 @@
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,17): error TS1187: A parameter property may not be declared using a binding pattern.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,27): error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x1' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,31): error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x2' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,35): error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x3' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,27): error TS2459: Type 'ObjType1' has no property 'x1' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,31): error TS2459: Type 'ObjType1' has no property 'x2' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(5,35): error TS2459: Type 'ObjType1' has no property 'x3' and no string index signature.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(7,29): error TS2339: Property 'x1' does not exist on type 'C1'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(7,40): error TS2339: Property 'x2' does not exist on type 'C1'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(7,51): error TS2339: Property 'x3' does not exist on type 'C1'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(7,62): error TS2339: Property 'y' does not exist on type 'C1'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(7,72): error TS2339: Property 'z' does not exist on type 'C1'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(11,19): error TS2345: Argument of type '[{ x1: number; x2: string; x3: boolean; }, string, boolean]' is not assignable to parameter of type '[{ x: number; y: string; z: boolean; }, number, string]'.
Type '{ x1: number; x2: string; x3: boolean; }' is not assignable to type '{ x: number; y: string; z: boolean; }'.
Object literal may only specify known properties, and 'x1' does not exist in type '{ x: number; y: string; z: boolean; }'.
tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(11,19): error TS2345: Argument of type '[{ x1: number; x2: string; x3: boolean; }, string, boolean]' is not assignable to parameter of type '[ObjType1, number, string]'.
Type '{ x1: number; x2: string; x3: boolean; }' is not assignable to type 'ObjType1'.
Object literal may only specify known properties, and 'x1' does not exist in type 'ObjType1'.
==== tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts (10 errors) ====
@ -21,11 +21,11 @@ tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1187: A parameter property may not be declared using a binding pattern.
~~
!!! error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x1' and no string index signature.
!!! error TS2459: Type 'ObjType1' has no property 'x1' and no string index signature.
~~
!!! error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x2' and no string index signature.
!!! error TS2459: Type 'ObjType1' has no property 'x2' and no string index signature.
~~
!!! error TS2459: Type '{ x: number; y: string; z: boolean; }' has no property 'x3' and no string index signature.
!!! error TS2459: Type 'ObjType1' has no property 'x3' and no string index signature.
var foo: any = x1 || x2 || x3 || y || z;
var bar: any = this.x1 || this.x2 || this.x3 || this.y || this.z;
~~
@ -43,7 +43,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterProperties5.ts(1
var a = new C1([{ x1: 10, x2: "", x3: true }, "", false]);
~~~~~~
!!! error TS2345: Argument of type '[{ x1: number; x2: string; x3: boolean; }, string, boolean]' is not assignable to parameter of type '[{ x: number; y: string; z: boolean; }, number, string]'.
!!! error TS2345: Type '{ x1: number; x2: string; x3: boolean; }' is not assignable to type '{ x: number; y: string; z: boolean; }'.
!!! error TS2345: Object literal may only specify known properties, and 'x1' does not exist in type '{ x: number; y: string; z: boolean; }'.
!!! error TS2345: Argument of type '[{ x1: number; x2: string; x3: boolean; }, string, boolean]' is not assignable to parameter of type '[ObjType1, number, string]'.
!!! error TS2345: Type '{ x1: number; x2: string; x3: boolean; }' is not assignable to type 'ObjType1'.
!!! error TS2345: Object literal may only specify known properties, and 'x1' does not exist in type 'ObjType1'.
var [a_x1, a_x2, a_x3, a_y, a_z] = [a.x1, a.x2, a.x3, a.y, a.z];

View file

@ -1,6 +1,6 @@
=== tests/cases/compiler/implicitIndexSignatures.ts ===
type StringMap = { [x: string]: string };
>StringMap : { [x: string]: string; }
>StringMap : StringMap
>x : string
const empty1 = {};
@ -24,12 +24,12 @@ let names2: { a: string, b: string };
>b : string
let map: StringMap;
>map : { [x: string]: string; }
>StringMap : { [x: string]: string; }
>map : StringMap
>StringMap : StringMap
map = { x: "xxx", y: "yyy" };
>map = { x: "xxx", y: "yyy" } : { x: string; y: string; }
>map : { [x: string]: string; }
>map : StringMap
>{ x: "xxx", y: "yyy" } : { x: string; y: string; }
>x : string
>"xxx" : "xxx"
@ -38,22 +38,22 @@ map = { x: "xxx", y: "yyy" };
map = empty1;
>map = empty1 : {}
>map : { [x: string]: string; }
>map : StringMap
>empty1 : {}
map = empty2;
>map = empty2 : {}
>map : { [x: string]: string; }
>map : StringMap
>empty2 : {}
map = names1;
>map = names1 : { a: string; b: string; }
>map : { [x: string]: string; }
>map : StringMap
>names1 : { a: string; b: string; }
map = names2;
>map = names2 : { a: string; b: string; }
>map : { [x: string]: string; }
>map : StringMap
>names2 : { a: string; b: string; }
declare function getStringIndexValue<T>(map: { [x: string]: T }): T;

View file

@ -189,7 +189,7 @@ var z: Z4;
// Repro from #9919
type ToString = {
>ToString : { toString(): string; }
>ToString : ToString
toString(): string;
>toString : () => string
@ -207,18 +207,18 @@ type BoxedValue = { kind: 'int', num: number }
type IntersectionFail = BoxedValue & ToString
>IntersectionFail : IntersectionFail
>BoxedValue : BoxedValue
>ToString : { toString(): string; }
>ToString : ToString
type IntersectionInline = { kind: 'int', num: number } & ToString
>IntersectionInline : IntersectionInline
>kind : "int"
>num : number
>ToString : { toString(): string; }
>ToString : ToString
| { kind: 'string', str: string } & ToString
>kind : "string"
>str : string
>ToString : { toString(): string; }
>ToString : ToString
function getValueAsString(value: IntersectionFail): string {
>getValueAsString : (value: IntersectionFail) => string
@ -236,11 +236,11 @@ function getValueAsString(value: IntersectionFail): string {
>'' + value.num : string
>'' : ""
>value.num : number
>value : { kind: "int"; num: number; } & { toString(): string; }
>value : { kind: "int"; num: number; } & ToString
>num : number
}
return value.str;
>value.str : string
>value : { kind: "string"; str: string; } & { toString(): string; }
>value : { kind: "string"; str: string; } & ToString
>str : string
}

View file

@ -42,7 +42,7 @@ class Options {
}
type Dictionary<T> = { [x: string]: T };
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>T : T
>x : string
>T : T
@ -88,7 +88,7 @@ type K11 = keyof Shape[]; // number | "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string | number
>K12 : string | number
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>Shape : Shape
type K13 = keyof {}; // never
@ -128,7 +128,7 @@ type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
type K21 = KeyOf<Dictionary<Shape>>; // string | number
>K21 : string | number
>KeyOf : keyof T
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>Shape : Shape
type NAME = "name";
@ -201,17 +201,17 @@ type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false
type Q50 = Dictionary<Shape>["howdy"]; // Shape
>Q50 : Shape
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>Shape : Shape
type Q51 = Dictionary<Shape>[123]; // Shape
>Q51 : Shape
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>Shape : Shape
type Q52 = Dictionary<Shape>[E.B]; // Shape
>Q52 : Shape
>Dictionary : { [x: string]: T; }
>Dictionary : Dictionary<T>
>Shape : Shape
>E : any
>B : E.B

View file

@ -0,0 +1,110 @@
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(34,20): error TS2313: Type parameter 'P' has a circular constraint.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(35,20): error TS2322: Type 'Date' is not assignable to type 'string | number'.
Type 'Date' is not assignable to type 'number'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(36,19): error TS2344: Type 'Date' does not satisfy the constraint 'string | number'.
Type 'Date' is not assignable to type 'number'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(39,24): error TS2344: Type '"foo"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(40,24): error TS2344: Type '"name" | "foo"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
Type '"foo"' is not assignable to type '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(42,24): error TS2344: Type '"x" | "y"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
Type '"x"' is not assignable to type '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(44,24): error TS2344: Type 'undefined' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(47,24): error TS2344: Type 'T' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
Type 'T' is not assignable to type '"visible"'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(51,24): error TS2344: Type 'T' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
Type 'string | number' is not assignable to type '"name" | "width" | "height" | "visible"'.
Type 'string' is not assignable to type '"name" | "width" | "height" | "visible"'.
Type 'T' is not assignable to type '"visible"'.
Type 'string | number' is not assignable to type '"visible"'.
Type 'string' is not assignable to type '"visible"'.
==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (9 errors) ====
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string | number, T> = {
[_ in K]: T;
}
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface Named {
name: string;
}
interface Point {
x: number;
y: number;
}
type T00 = { [P in P]: string }; // Error
~
!!! error TS2313: Type parameter 'P' has a circular constraint.
type T01 = { [P in Date]: number }; // Error
~~~~
!!! error TS2322: Type 'Date' is not assignable to type 'string | number'.
!!! error TS2322: Type 'Date' is not assignable to type 'number'.
type T02 = Record<Date, number>; // Error
~~~~
!!! error TS2344: Type 'Date' does not satisfy the constraint 'string | number'.
!!! error TS2344: Type 'Date' is not assignable to type 'number'.
type T10 = Pick<Shape, "name">;
type T11 = Pick<Shape, "foo">; // Error
~~~~~
!!! error TS2344: Type '"foo"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
type T12 = Pick<Shape, "name" | "foo">; // Error
~~~~~~~~~~~~~~
!!! error TS2344: Type '"name" | "foo"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type '"foo"' is not assignable to type '"name" | "width" | "height" | "visible"'.
type T13 = Pick<Shape, keyof Named>;
type T14 = Pick<Shape, keyof Point>; // Error
~~~~~~~~~~~
!!! error TS2344: Type '"x" | "y"' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type '"x"' is not assignable to type '"name" | "width" | "height" | "visible"'.
type T15 = Pick<Shape, never>;
type T16 = Pick<Shape, undefined>; // Error
~~~~~~~~~
!!! error TS2344: Type 'undefined' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
function f1<T>(x: T) {
let y: Pick<Shape, T>; // Error
~
!!! error TS2344: Type 'T' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type 'T' is not assignable to type '"visible"'.
}
function f2<T extends string | number>(x: T) {
let y: Pick<Shape, T>; // Error
~
!!! error TS2344: Type 'T' does not satisfy the constraint '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type 'string | number' is not assignable to type '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type 'string' is not assignable to type '"name" | "width" | "height" | "visible"'.
!!! error TS2344: Type 'T' is not assignable to type '"visible"'.
!!! error TS2344: Type 'string | number' is not assignable to type '"visible"'.
!!! error TS2344: Type 'string' is not assignable to type '"visible"'.
}
function f3<T extends keyof Shape>(x: T) {
let y: Pick<Shape, T>;
}
function f4<T extends keyof Named>(x: T) {
let y: Pick<Shape, T>;
}

View file

@ -0,0 +1,121 @@
//// [mappedTypeErrors.ts]
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string | number, T> = {
[_ in K]: T;
}
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface Named {
name: string;
}
interface Point {
x: number;
y: number;
}
type T00 = { [P in P]: string }; // Error
type T01 = { [P in Date]: number }; // Error
type T02 = Record<Date, number>; // Error
type T10 = Pick<Shape, "name">;
type T11 = Pick<Shape, "foo">; // Error
type T12 = Pick<Shape, "name" | "foo">; // Error
type T13 = Pick<Shape, keyof Named>;
type T14 = Pick<Shape, keyof Point>; // Error
type T15 = Pick<Shape, never>;
type T16 = Pick<Shape, undefined>; // Error
function f1<T>(x: T) {
let y: Pick<Shape, T>; // Error
}
function f2<T extends string | number>(x: T) {
let y: Pick<Shape, T>; // Error
}
function f3<T extends keyof Shape>(x: T) {
let y: Pick<Shape, T>;
}
function f4<T extends keyof Named>(x: T) {
let y: Pick<Shape, T>;
}
//// [mappedTypeErrors.js]
function f1(x) {
var y; // Error
}
function f2(x) {
var y; // Error
}
function f3(x) {
var y;
}
function f4(x) {
var y;
}
//// [mappedTypeErrors.d.ts]
declare type Partial<T> = {
[P in keyof T]?: T[P];
};
declare type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
declare type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
declare type Record<K extends string | number, T> = {
[_ in K]: T;
};
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface Named {
name: string;
}
interface Point {
x: number;
y: number;
}
declare type T00 = {
[P in P]: string;
};
declare type T01 = {
[P in Date]: number;
};
declare type T02 = Record<Date, number>;
declare type T10 = Pick<Shape, "name">;
declare type T11 = Pick<Shape, "foo">;
declare type T12 = Pick<Shape, "name" | "foo">;
declare type T13 = Pick<Shape, keyof Named>;
declare type T14 = Pick<Shape, keyof Point>;
declare type T15 = Pick<Shape, never>;
declare type T16 = Pick<Shape, undefined>;
declare function f1<T>(x: T): void;
declare function f2<T extends string | number>(x: T): void;
declare function f3<T extends keyof Shape>(x: T): void;
declare function f4<T extends keyof Named>(x: T): void;

View file

@ -0,0 +1,179 @@
//// [mappedTypes1.ts]
type Item = { a: string, b: number, c: boolean };
type T00 = { [P in "x" | "y"]: number };
type T01 = { [P in "x" | "y"]: P };
type T02 = { [P in "a" | "b"]: Item[P]; }
type T03 = { [P in keyof Item]: Date };
type T10 = { [P in keyof Item]: Item[P] };
type T11 = { [P in keyof Item]?: Item[P] };
type T12 = { readonly [P in keyof Item]: Item[P] };
type T13 = { readonly [P in keyof Item]?: Item[P] };
type T20 = { [P in keyof Item]: Item[P] | null };
type T21 = { [P in keyof Item]: Array<Item[P]> };
type T30 = { [P in keyof any]: void };
type T31 = { [P in keyof string]: void };
type T32 = { [P in keyof number]: void };
type T33 = { [P in keyof boolean]: void };
type T34 = { [P in keyof undefined]: void };
type T35 = { [P in keyof null]: void };
type T36 = { [P in keyof void]: void };
type T37 = { [P in keyof symbol]: void };
type T38 = { [P in keyof never]: void };
type T40 = { [P in string]: void };
type T41 = { [P in number]: void };
type T42 = { [P in string | number]: void };
type T43 = { [P in "a" | "b" | 0 | 1]: void };
type T44 = { [P in "a" | "b" | "0" | "1"]: void };
type T45 = { [P in "a" | "b" | "0" | "1" | 0 | 1]: void };
type T46 = { [P in number | "a" | "b" | 0 | 1]: void };
type T47 = { [P in string | number | "a" | "b" | 0 | 1]: void };
declare function f1<T1>(): { [P in keyof T1]: void };
declare function f2<T1 extends string>(): { [P in keyof T1]: void };
declare function f3<T1 extends number>(): { [P in keyof T1]: void };
let x1 = f1();
let x2 = f2();
let x3 = f3();
//// [mappedTypes1.js]
var x1 = f1();
var x2 = f2();
var x3 = f3();
//// [mappedTypes1.d.ts]
declare type Item = {
a: string;
b: number;
c: boolean;
};
declare type T00 = {
[P in "x" | "y"]: number;
};
declare type T01 = {
[P in "x" | "y"]: P;
};
declare type T02 = {
[P in "a" | "b"]: Item[P];
};
declare type T03 = {
[P in keyof Item]: Date;
};
declare type T10 = {
[P in keyof Item]: Item[P];
};
declare type T11 = {
[P in keyof Item]?: Item[P];
};
declare type T12 = {
readonly [P in keyof Item]: Item[P];
};
declare type T13 = {
readonly [P in keyof Item]?: Item[P];
};
declare type T20 = {
[P in keyof Item]: Item[P] | null;
};
declare type T21 = {
[P in keyof Item]: Array<Item[P]>;
};
declare type T30 = {
[P in keyof any]: void;
};
declare type T31 = {
[P in keyof string]: void;
};
declare type T32 = {
[P in keyof number]: void;
};
declare type T33 = {
[P in keyof boolean]: void;
};
declare type T34 = {
[P in keyof undefined]: void;
};
declare type T35 = {
[P in keyof null]: void;
};
declare type T36 = {
[P in keyof void]: void;
};
declare type T37 = {
[P in keyof symbol]: void;
};
declare type T38 = {
[P in keyof never]: void;
};
declare type T40 = {
[P in string]: void;
};
declare type T41 = {
[P in number]: void;
};
declare type T42 = {
[P in string | number]: void;
};
declare type T43 = {
[P in "a" | "b" | 0 | 1]: void;
};
declare type T44 = {
[P in "a" | "b" | "0" | "1"]: void;
};
declare type T45 = {
[P in "a" | "b" | "0" | "1" | 0 | 1]: void;
};
declare type T46 = {
[P in number | "a" | "b" | 0 | 1]: void;
};
declare type T47 = {
[P in string | number | "a" | "b" | 0 | 1]: void;
};
declare function f1<T1>(): {
[P in keyof T1]: void;
};
declare function f2<T1 extends string>(): {
[P in keyof T1]: void;
};
declare function f3<T1 extends number>(): {
[P in keyof T1]: void;
};
declare let x1: {};
declare let x2: {
[x: number]: void;
toString: void;
charAt: void;
charCodeAt: void;
concat: void;
indexOf: void;
lastIndexOf: void;
localeCompare: void;
match: void;
replace: void;
search: void;
slice: void;
split: void;
substring: void;
toLowerCase: void;
toLocaleLowerCase: void;
toUpperCase: void;
toLocaleUpperCase: void;
trim: void;
length: void;
substr: void;
valueOf: void;
};
declare let x3: {
toString: void;
valueOf: void;
toFixed: void;
toExponential: void;
toPrecision: void;
toLocaleString: void;
};

View file

@ -0,0 +1,170 @@
=== tests/cases/conformance/types/mapped/mappedTypes1.ts ===
type Item = { a: string, b: number, c: boolean };
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>a : Symbol(a, Decl(mappedTypes1.ts, 1, 13))
>b : Symbol(b, Decl(mappedTypes1.ts, 1, 24))
>c : Symbol(c, Decl(mappedTypes1.ts, 1, 35))
type T00 = { [P in "x" | "y"]: number };
>T00 : Symbol(T00, Decl(mappedTypes1.ts, 1, 49))
>P : Symbol(P, Decl(mappedTypes1.ts, 3, 14))
type T01 = { [P in "x" | "y"]: P };
>T01 : Symbol(T01, Decl(mappedTypes1.ts, 3, 40))
>P : Symbol(P, Decl(mappedTypes1.ts, 4, 14))
>P : Symbol(P, Decl(mappedTypes1.ts, 4, 14))
type T02 = { [P in "a" | "b"]: Item[P]; }
>T02 : Symbol(T02, Decl(mappedTypes1.ts, 4, 35))
>P : Symbol(P, Decl(mappedTypes1.ts, 5, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 5, 14))
type T03 = { [P in keyof Item]: Date };
>T03 : Symbol(T03, Decl(mappedTypes1.ts, 5, 41))
>P : Symbol(P, Decl(mappedTypes1.ts, 6, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
type T10 = { [P in keyof Item]: Item[P] };
>T10 : Symbol(T10, Decl(mappedTypes1.ts, 6, 39))
>P : Symbol(P, Decl(mappedTypes1.ts, 8, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 8, 14))
type T11 = { [P in keyof Item]?: Item[P] };
>T11 : Symbol(T11, Decl(mappedTypes1.ts, 8, 42))
>P : Symbol(P, Decl(mappedTypes1.ts, 9, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 9, 14))
type T12 = { readonly [P in keyof Item]: Item[P] };
>T12 : Symbol(T12, Decl(mappedTypes1.ts, 9, 43))
>P : Symbol(P, Decl(mappedTypes1.ts, 10, 23))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 10, 23))
type T13 = { readonly [P in keyof Item]?: Item[P] };
>T13 : Symbol(T13, Decl(mappedTypes1.ts, 10, 51))
>P : Symbol(P, Decl(mappedTypes1.ts, 11, 23))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 11, 23))
type T20 = { [P in keyof Item]: Item[P] | null };
>T20 : Symbol(T20, Decl(mappedTypes1.ts, 11, 52))
>P : Symbol(P, Decl(mappedTypes1.ts, 13, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 13, 14))
type T21 = { [P in keyof Item]: Array<Item[P]> };
>T21 : Symbol(T21, Decl(mappedTypes1.ts, 13, 49))
>P : Symbol(P, Decl(mappedTypes1.ts, 14, 14))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>Item : Symbol(Item, Decl(mappedTypes1.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes1.ts, 14, 14))
type T30 = { [P in keyof any]: void };
>T30 : Symbol(T30, Decl(mappedTypes1.ts, 14, 49))
>P : Symbol(P, Decl(mappedTypes1.ts, 16, 14))
type T31 = { [P in keyof string]: void };
>T31 : Symbol(T31, Decl(mappedTypes1.ts, 16, 38))
>P : Symbol(P, Decl(mappedTypes1.ts, 17, 14))
type T32 = { [P in keyof number]: void };
>T32 : Symbol(T32, Decl(mappedTypes1.ts, 17, 41))
>P : Symbol(P, Decl(mappedTypes1.ts, 18, 14))
type T33 = { [P in keyof boolean]: void };
>T33 : Symbol(T33, Decl(mappedTypes1.ts, 18, 41))
>P : Symbol(P, Decl(mappedTypes1.ts, 19, 14))
type T34 = { [P in keyof undefined]: void };
>T34 : Symbol(T34, Decl(mappedTypes1.ts, 19, 42))
>P : Symbol(P, Decl(mappedTypes1.ts, 20, 14))
type T35 = { [P in keyof null]: void };
>T35 : Symbol(T35, Decl(mappedTypes1.ts, 20, 44))
>P : Symbol(P, Decl(mappedTypes1.ts, 21, 14))
type T36 = { [P in keyof void]: void };
>T36 : Symbol(T36, Decl(mappedTypes1.ts, 21, 39))
>P : Symbol(P, Decl(mappedTypes1.ts, 22, 14))
type T37 = { [P in keyof symbol]: void };
>T37 : Symbol(T37, Decl(mappedTypes1.ts, 22, 39))
>P : Symbol(P, Decl(mappedTypes1.ts, 23, 14))
type T38 = { [P in keyof never]: void };
>T38 : Symbol(T38, Decl(mappedTypes1.ts, 23, 41))
>P : Symbol(P, Decl(mappedTypes1.ts, 24, 14))
type T40 = { [P in string]: void };
>T40 : Symbol(T40, Decl(mappedTypes1.ts, 24, 40))
>P : Symbol(P, Decl(mappedTypes1.ts, 26, 14))
type T41 = { [P in number]: void };
>T41 : Symbol(T41, Decl(mappedTypes1.ts, 26, 35))
>P : Symbol(P, Decl(mappedTypes1.ts, 27, 14))
type T42 = { [P in string | number]: void };
>T42 : Symbol(T42, Decl(mappedTypes1.ts, 27, 35))
>P : Symbol(P, Decl(mappedTypes1.ts, 28, 14))
type T43 = { [P in "a" | "b" | 0 | 1]: void };
>T43 : Symbol(T43, Decl(mappedTypes1.ts, 28, 44))
>P : Symbol(P, Decl(mappedTypes1.ts, 29, 14))
type T44 = { [P in "a" | "b" | "0" | "1"]: void };
>T44 : Symbol(T44, Decl(mappedTypes1.ts, 29, 46))
>P : Symbol(P, Decl(mappedTypes1.ts, 30, 14))
type T45 = { [P in "a" | "b" | "0" | "1" | 0 | 1]: void };
>T45 : Symbol(T45, Decl(mappedTypes1.ts, 30, 50))
>P : Symbol(P, Decl(mappedTypes1.ts, 31, 14))
type T46 = { [P in number | "a" | "b" | 0 | 1]: void };
>T46 : Symbol(T46, Decl(mappedTypes1.ts, 31, 58))
>P : Symbol(P, Decl(mappedTypes1.ts, 32, 14))
type T47 = { [P in string | number | "a" | "b" | 0 | 1]: void };
>T47 : Symbol(T47, Decl(mappedTypes1.ts, 32, 55))
>P : Symbol(P, Decl(mappedTypes1.ts, 33, 14))
declare function f1<T1>(): { [P in keyof T1]: void };
>f1 : Symbol(f1, Decl(mappedTypes1.ts, 33, 64))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 35, 20))
>P : Symbol(P, Decl(mappedTypes1.ts, 35, 30))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 35, 20))
declare function f2<T1 extends string>(): { [P in keyof T1]: void };
>f2 : Symbol(f2, Decl(mappedTypes1.ts, 35, 53))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 36, 20))
>P : Symbol(P, Decl(mappedTypes1.ts, 36, 45))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 36, 20))
declare function f3<T1 extends number>(): { [P in keyof T1]: void };
>f3 : Symbol(f3, Decl(mappedTypes1.ts, 36, 68))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 37, 20))
>P : Symbol(P, Decl(mappedTypes1.ts, 37, 45))
>T1 : Symbol(T1, Decl(mappedTypes1.ts, 37, 20))
let x1 = f1();
>x1 : Symbol(x1, Decl(mappedTypes1.ts, 39, 3))
>f1 : Symbol(f1, Decl(mappedTypes1.ts, 33, 64))
let x2 = f2();
>x2 : Symbol(x2, Decl(mappedTypes1.ts, 40, 3))
>f2 : Symbol(f2, Decl(mappedTypes1.ts, 35, 53))
let x3 = f3();
>x3 : Symbol(x3, Decl(mappedTypes1.ts, 41, 3))
>f3 : Symbol(f3, Decl(mappedTypes1.ts, 36, 68))

View file

@ -0,0 +1,175 @@
=== tests/cases/conformance/types/mapped/mappedTypes1.ts ===
type Item = { a: string, b: number, c: boolean };
>Item : Item
>a : string
>b : number
>c : boolean
type T00 = { [P in "x" | "y"]: number };
>T00 : T00
>P : P
type T01 = { [P in "x" | "y"]: P };
>T01 : T01
>P : P
>P : P
type T02 = { [P in "a" | "b"]: Item[P]; }
>T02 : T02
>P : P
>Item : Item
>P : P
type T03 = { [P in keyof Item]: Date };
>T03 : T03
>P : P
>Item : Item
>Date : Date
type T10 = { [P in keyof Item]: Item[P] };
>T10 : T10
>P : P
>Item : Item
>Item : Item
>P : P
type T11 = { [P in keyof Item]?: Item[P] };
>T11 : T11
>P : P
>Item : Item
>Item : Item
>P : P
type T12 = { readonly [P in keyof Item]: Item[P] };
>T12 : T12
>P : P
>Item : Item
>Item : Item
>P : P
type T13 = { readonly [P in keyof Item]?: Item[P] };
>T13 : T13
>P : P
>Item : Item
>Item : Item
>P : P
type T20 = { [P in keyof Item]: Item[P] | null };
>T20 : T20
>P : P
>Item : Item
>Item : Item
>P : P
>null : null
type T21 = { [P in keyof Item]: Array<Item[P]> };
>T21 : T21
>P : P
>Item : Item
>Array : T[]
>Item : Item
>P : P
type T30 = { [P in keyof any]: void };
>T30 : T30
>P : P
type T31 = { [P in keyof string]: void };
>T31 : T31
>P : P
type T32 = { [P in keyof number]: void };
>T32 : T32
>P : P
type T33 = { [P in keyof boolean]: void };
>T33 : T33
>P : P
type T34 = { [P in keyof undefined]: void };
>T34 : T34
>P : P
type T35 = { [P in keyof null]: void };
>T35 : T35
>P : P
>null : null
type T36 = { [P in keyof void]: void };
>T36 : T36
>P : P
type T37 = { [P in keyof symbol]: void };
>T37 : T37
>P : P
type T38 = { [P in keyof never]: void };
>T38 : T38
>P : P
type T40 = { [P in string]: void };
>T40 : T40
>P : P
type T41 = { [P in number]: void };
>T41 : T41
>P : P
type T42 = { [P in string | number]: void };
>T42 : T42
>P : P
type T43 = { [P in "a" | "b" | 0 | 1]: void };
>T43 : T43
>P : P
type T44 = { [P in "a" | "b" | "0" | "1"]: void };
>T44 : T44
>P : P
type T45 = { [P in "a" | "b" | "0" | "1" | 0 | 1]: void };
>T45 : T45
>P : P
type T46 = { [P in number | "a" | "b" | 0 | 1]: void };
>T46 : T46
>P : P
type T47 = { [P in string | number | "a" | "b" | 0 | 1]: void };
>T47 : T47
>P : P
declare function f1<T1>(): { [P in keyof T1]: void };
>f1 : <T1>() => { [P in keyof T1]: void; }
>T1 : T1
>P : P
>T1 : T1
declare function f2<T1 extends string>(): { [P in keyof T1]: void };
>f2 : <T1 extends string>() => { [P in keyof T1]: void; }
>T1 : T1
>P : P
>T1 : T1
declare function f3<T1 extends number>(): { [P in keyof T1]: void };
>f3 : <T1 extends number>() => { [P in keyof T1]: void; }
>T1 : T1
>P : P
>T1 : T1
let x1 = f1();
>x1 : {}
>f1() : {}
>f1 : <T1>() => { [P in keyof T1]: void; }
let x2 = f2();
>x2 : { [x: number]: void; toString: void; charAt: void; charCodeAt: void; concat: void; indexOf: void; lastIndexOf: void; localeCompare: void; match: void; replace: void; search: void; slice: void; split: void; substring: void; toLowerCase: void; toLocaleLowerCase: void; toUpperCase: void; toLocaleUpperCase: void; trim: void; length: void; substr: void; valueOf: void; }
>f2() : { [x: number]: void; toString: void; charAt: void; charCodeAt: void; concat: void; indexOf: void; lastIndexOf: void; localeCompare: void; match: void; replace: void; search: void; slice: void; split: void; substring: void; toLowerCase: void; toLocaleLowerCase: void; toUpperCase: void; toLocaleUpperCase: void; trim: void; length: void; substr: void; valueOf: void; }
>f2 : <T1 extends string>() => { [P in keyof T1]: void; }
let x3 = f3();
>x3 : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>f3() : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>f3 : <T1 extends number>() => { [P in keyof T1]: void; }

View file

@ -0,0 +1,183 @@
//// [mappedTypes2.ts]
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string | number, T> = {
[_ in K]: T;
}
type Proxy<T> = {
get(): T;
set(value: T): void;
}
type Proxify<T> = {
[P in keyof T]: Proxy<T[P]>;
}
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
declare function assign<T>(obj: T, props: Partial<T>): void;
declare function freeze<T>(obj: T): Readonly<T>;
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
declare function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;
declare function proxify<T>(obj: T): Proxify<T>;
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface PartialShape {
name?: string;
width?: number;
height?: number;
visible?: boolean;
}
interface ReadonlyShape {
readonly name: string;
readonly width: number;
readonly height: number;
readonly visible: boolean;
}
function f0(s1: Shape, s2: Shape) {
assign(s1, { name: "circle" });
assign(s2, { width: 10, height: 20 });
}
function f1(shape: Shape) {
var frozen: ReadonlyShape;
var frozen: Readonly<Shape>;
var frozen = freeze(shape);
}
function f2(shape: Shape) {
var partial: PartialShape;
var partial: Partial<Shape>;
var partial: Partial<Shape> = {};
}
function f3(shape: Shape) {
const x = pick(shape, "name", "visible"); // { name: string, visible: boolean }
}
function f4() {
const rec = { foo: "hello", bar: "world", baz: "bye" };
const lengths = mapObject(rec, s => s.length); // { foo: number, bar: number, baz: number }
}
function f5(shape: Shape) {
const p = proxify(shape);
let name = p.name.get();
p.visible.set(false);
}
function f6(shape: DeepReadonly<Shape>) {
let name = shape.name; // DeepReadonly<string>
let length = name.length; // DeepReadonly<number>
let toString = length.toString; // DeepReadonly<(radix?: number) => string>
}
//// [mappedTypes2.js]
function f0(s1, s2) {
assign(s1, { name: "circle" });
assign(s2, { width: 10, height: 20 });
}
function f1(shape) {
var frozen;
var frozen;
var frozen = freeze(shape);
}
function f2(shape) {
var partial;
var partial;
var partial = {};
}
function f3(shape) {
var x = pick(shape, "name", "visible"); // { name: string, visible: boolean }
}
function f4() {
var rec = { foo: "hello", bar: "world", baz: "bye" };
var lengths = mapObject(rec, function (s) { return s.length; }); // { foo: number, bar: number, baz: number }
}
function f5(shape) {
var p = proxify(shape);
var name = p.name.get();
p.visible.set(false);
}
function f6(shape) {
var name = shape.name; // DeepReadonly<string>
var length = name.length; // DeepReadonly<number>
var toString = length.toString; // DeepReadonly<(radix?: number) => string>
}
//// [mappedTypes2.d.ts]
declare type Partial<T> = {
[P in keyof T]?: T[P];
};
declare type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
declare type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
declare type Record<K extends string | number, T> = {
[_ in K]: T;
};
declare type Proxy<T> = {
get(): T;
set(value: T): void;
};
declare type Proxify<T> = {
[P in keyof T]: Proxy<T[P]>;
};
declare type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
declare function assign<T>(obj: T, props: Partial<T>): void;
declare function freeze<T>(obj: T): Readonly<T>;
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
declare function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;
declare function proxify<T>(obj: T): Proxify<T>;
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface PartialShape {
name?: string;
width?: number;
height?: number;
visible?: boolean;
}
interface ReadonlyShape {
readonly name: string;
readonly width: number;
readonly height: number;
readonly visible: boolean;
}
declare function f0(s1: Shape, s2: Shape): void;
declare function f1(shape: Shape): void;
declare function f2(shape: Shape): void;
declare function f3(shape: Shape): void;
declare function f4(): void;
declare function f5(shape: Shape): void;
declare function f6(shape: DeepReadonly<Shape>): void;

View file

@ -0,0 +1,331 @@
=== tests/cases/conformance/types/mapped/mappedTypes2.ts ===
type Partial<T> = {
>Partial : Symbol(Partial, Decl(mappedTypes2.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypes2.ts, 1, 13))
[P in keyof T]?: T[P];
>P : Symbol(P, Decl(mappedTypes2.ts, 2, 5))
>T : Symbol(T, Decl(mappedTypes2.ts, 1, 13))
>T : Symbol(T, Decl(mappedTypes2.ts, 1, 13))
>P : Symbol(P, Decl(mappedTypes2.ts, 2, 5))
};
type Readonly<T> = {
>Readonly : Symbol(Readonly, Decl(mappedTypes2.ts, 3, 2))
>T : Symbol(T, Decl(mappedTypes2.ts, 5, 14))
readonly [P in keyof T]: T[P];
>P : Symbol(P, Decl(mappedTypes2.ts, 6, 14))
>T : Symbol(T, Decl(mappedTypes2.ts, 5, 14))
>T : Symbol(T, Decl(mappedTypes2.ts, 5, 14))
>P : Symbol(P, Decl(mappedTypes2.ts, 6, 14))
};
type Pick<T, K extends keyof T> = {
>Pick : Symbol(Pick, Decl(mappedTypes2.ts, 7, 2))
>T : Symbol(T, Decl(mappedTypes2.ts, 9, 10))
>K : Symbol(K, Decl(mappedTypes2.ts, 9, 12))
>T : Symbol(T, Decl(mappedTypes2.ts, 9, 10))
[P in K]: T[P];
>P : Symbol(P, Decl(mappedTypes2.ts, 10, 5))
>K : Symbol(K, Decl(mappedTypes2.ts, 9, 12))
>T : Symbol(T, Decl(mappedTypes2.ts, 9, 10))
>P : Symbol(P, Decl(mappedTypes2.ts, 10, 5))
}
type Record<K extends string | number, T> = {
>Record : Symbol(Record, Decl(mappedTypes2.ts, 11, 1))
>K : Symbol(K, Decl(mappedTypes2.ts, 13, 12))
>T : Symbol(T, Decl(mappedTypes2.ts, 13, 38))
[_ in K]: T;
>_ : Symbol(_, Decl(mappedTypes2.ts, 14, 5))
>K : Symbol(K, Decl(mappedTypes2.ts, 13, 12))
>T : Symbol(T, Decl(mappedTypes2.ts, 13, 38))
}
type Proxy<T> = {
>Proxy : Symbol(Proxy, Decl(mappedTypes2.ts, 15, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 17, 11))
get(): T;
>get : Symbol(get, Decl(mappedTypes2.ts, 17, 17))
>T : Symbol(T, Decl(mappedTypes2.ts, 17, 11))
set(value: T): void;
>set : Symbol(set, Decl(mappedTypes2.ts, 18, 13))
>value : Symbol(value, Decl(mappedTypes2.ts, 19, 8))
>T : Symbol(T, Decl(mappedTypes2.ts, 17, 11))
}
type Proxify<T> = {
>Proxify : Symbol(Proxify, Decl(mappedTypes2.ts, 20, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 22, 13))
[P in keyof T]: Proxy<T[P]>;
>P : Symbol(P, Decl(mappedTypes2.ts, 23, 5))
>T : Symbol(T, Decl(mappedTypes2.ts, 22, 13))
>Proxy : Symbol(Proxy, Decl(mappedTypes2.ts, 15, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 22, 13))
>P : Symbol(P, Decl(mappedTypes2.ts, 23, 5))
}
type DeepReadonly<T> = {
>DeepReadonly : Symbol(DeepReadonly, Decl(mappedTypes2.ts, 24, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 26, 18))
readonly [P in keyof T]: DeepReadonly<T[P]>;
>P : Symbol(P, Decl(mappedTypes2.ts, 27, 14))
>T : Symbol(T, Decl(mappedTypes2.ts, 26, 18))
>DeepReadonly : Symbol(DeepReadonly, Decl(mappedTypes2.ts, 24, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 26, 18))
>P : Symbol(P, Decl(mappedTypes2.ts, 27, 14))
};
declare function assign<T>(obj: T, props: Partial<T>): void;
>assign : Symbol(assign, Decl(mappedTypes2.ts, 28, 2))
>T : Symbol(T, Decl(mappedTypes2.ts, 30, 24))
>obj : Symbol(obj, Decl(mappedTypes2.ts, 30, 27))
>T : Symbol(T, Decl(mappedTypes2.ts, 30, 24))
>props : Symbol(props, Decl(mappedTypes2.ts, 30, 34))
>Partial : Symbol(Partial, Decl(mappedTypes2.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypes2.ts, 30, 24))
declare function freeze<T>(obj: T): Readonly<T>;
>freeze : Symbol(freeze, Decl(mappedTypes2.ts, 30, 60))
>T : Symbol(T, Decl(mappedTypes2.ts, 31, 24))
>obj : Symbol(obj, Decl(mappedTypes2.ts, 31, 27))
>T : Symbol(T, Decl(mappedTypes2.ts, 31, 24))
>Readonly : Symbol(Readonly, Decl(mappedTypes2.ts, 3, 2))
>T : Symbol(T, Decl(mappedTypes2.ts, 31, 24))
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
>pick : Symbol(pick, Decl(mappedTypes2.ts, 31, 48))
>T : Symbol(T, Decl(mappedTypes2.ts, 32, 22))
>K : Symbol(K, Decl(mappedTypes2.ts, 32, 24))
>T : Symbol(T, Decl(mappedTypes2.ts, 32, 22))
>obj : Symbol(obj, Decl(mappedTypes2.ts, 32, 44))
>T : Symbol(T, Decl(mappedTypes2.ts, 32, 22))
>keys : Symbol(keys, Decl(mappedTypes2.ts, 32, 51))
>K : Symbol(K, Decl(mappedTypes2.ts, 32, 24))
>Pick : Symbol(Pick, Decl(mappedTypes2.ts, 7, 2))
>T : Symbol(T, Decl(mappedTypes2.ts, 32, 22))
>K : Symbol(K, Decl(mappedTypes2.ts, 32, 24))
declare function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;
>mapObject : Symbol(mapObject, Decl(mappedTypes2.ts, 32, 78))
>K : Symbol(K, Decl(mappedTypes2.ts, 33, 27))
>T : Symbol(T, Decl(mappedTypes2.ts, 33, 53))
>U : Symbol(U, Decl(mappedTypes2.ts, 33, 56))
>obj : Symbol(obj, Decl(mappedTypes2.ts, 33, 60))
>Record : Symbol(Record, Decl(mappedTypes2.ts, 11, 1))
>K : Symbol(K, Decl(mappedTypes2.ts, 33, 27))
>T : Symbol(T, Decl(mappedTypes2.ts, 33, 53))
>f : Symbol(f, Decl(mappedTypes2.ts, 33, 78))
>x : Symbol(x, Decl(mappedTypes2.ts, 33, 83))
>T : Symbol(T, Decl(mappedTypes2.ts, 33, 53))
>U : Symbol(U, Decl(mappedTypes2.ts, 33, 56))
>Record : Symbol(Record, Decl(mappedTypes2.ts, 11, 1))
>K : Symbol(K, Decl(mappedTypes2.ts, 33, 27))
>U : Symbol(U, Decl(mappedTypes2.ts, 33, 56))
declare function proxify<T>(obj: T): Proxify<T>;
>proxify : Symbol(proxify, Decl(mappedTypes2.ts, 33, 109))
>T : Symbol(T, Decl(mappedTypes2.ts, 34, 25))
>obj : Symbol(obj, Decl(mappedTypes2.ts, 34, 28))
>T : Symbol(T, Decl(mappedTypes2.ts, 34, 25))
>Proxify : Symbol(Proxify, Decl(mappedTypes2.ts, 20, 1))
>T : Symbol(T, Decl(mappedTypes2.ts, 34, 25))
interface Shape {
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
name: string;
>name : Symbol(Shape.name, Decl(mappedTypes2.ts, 36, 17))
width: number;
>width : Symbol(Shape.width, Decl(mappedTypes2.ts, 37, 17))
height: number;
>height : Symbol(Shape.height, Decl(mappedTypes2.ts, 38, 18))
visible: boolean;
>visible : Symbol(Shape.visible, Decl(mappedTypes2.ts, 39, 19))
}
interface PartialShape {
>PartialShape : Symbol(PartialShape, Decl(mappedTypes2.ts, 41, 1))
name?: string;
>name : Symbol(PartialShape.name, Decl(mappedTypes2.ts, 43, 24))
width?: number;
>width : Symbol(PartialShape.width, Decl(mappedTypes2.ts, 44, 18))
height?: number;
>height : Symbol(PartialShape.height, Decl(mappedTypes2.ts, 45, 19))
visible?: boolean;
>visible : Symbol(PartialShape.visible, Decl(mappedTypes2.ts, 46, 20))
}
interface ReadonlyShape {
>ReadonlyShape : Symbol(ReadonlyShape, Decl(mappedTypes2.ts, 48, 1))
readonly name: string;
>name : Symbol(ReadonlyShape.name, Decl(mappedTypes2.ts, 50, 25))
readonly width: number;
>width : Symbol(ReadonlyShape.width, Decl(mappedTypes2.ts, 51, 26))
readonly height: number;
>height : Symbol(ReadonlyShape.height, Decl(mappedTypes2.ts, 52, 27))
readonly visible: boolean;
>visible : Symbol(ReadonlyShape.visible, Decl(mappedTypes2.ts, 53, 28))
}
function f0(s1: Shape, s2: Shape) {
>f0 : Symbol(f0, Decl(mappedTypes2.ts, 55, 1))
>s1 : Symbol(s1, Decl(mappedTypes2.ts, 57, 12))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
>s2 : Symbol(s2, Decl(mappedTypes2.ts, 57, 22))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
assign(s1, { name: "circle" });
>assign : Symbol(assign, Decl(mappedTypes2.ts, 28, 2))
>s1 : Symbol(s1, Decl(mappedTypes2.ts, 57, 12))
>name : Symbol(name, Decl(mappedTypes2.ts, 58, 16))
assign(s2, { width: 10, height: 20 });
>assign : Symbol(assign, Decl(mappedTypes2.ts, 28, 2))
>s2 : Symbol(s2, Decl(mappedTypes2.ts, 57, 22))
>width : Symbol(width, Decl(mappedTypes2.ts, 59, 16))
>height : Symbol(height, Decl(mappedTypes2.ts, 59, 27))
}
function f1(shape: Shape) {
>f1 : Symbol(f1, Decl(mappedTypes2.ts, 60, 1))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 62, 12))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
var frozen: ReadonlyShape;
>frozen : Symbol(frozen, Decl(mappedTypes2.ts, 63, 7), Decl(mappedTypes2.ts, 64, 7), Decl(mappedTypes2.ts, 65, 7))
>ReadonlyShape : Symbol(ReadonlyShape, Decl(mappedTypes2.ts, 48, 1))
var frozen: Readonly<Shape>;
>frozen : Symbol(frozen, Decl(mappedTypes2.ts, 63, 7), Decl(mappedTypes2.ts, 64, 7), Decl(mappedTypes2.ts, 65, 7))
>Readonly : Symbol(Readonly, Decl(mappedTypes2.ts, 3, 2))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
var frozen = freeze(shape);
>frozen : Symbol(frozen, Decl(mappedTypes2.ts, 63, 7), Decl(mappedTypes2.ts, 64, 7), Decl(mappedTypes2.ts, 65, 7))
>freeze : Symbol(freeze, Decl(mappedTypes2.ts, 30, 60))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 62, 12))
}
function f2(shape: Shape) {
>f2 : Symbol(f2, Decl(mappedTypes2.ts, 66, 1))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 68, 12))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
var partial: PartialShape;
>partial : Symbol(partial, Decl(mappedTypes2.ts, 69, 7), Decl(mappedTypes2.ts, 70, 7), Decl(mappedTypes2.ts, 71, 7))
>PartialShape : Symbol(PartialShape, Decl(mappedTypes2.ts, 41, 1))
var partial: Partial<Shape>;
>partial : Symbol(partial, Decl(mappedTypes2.ts, 69, 7), Decl(mappedTypes2.ts, 70, 7), Decl(mappedTypes2.ts, 71, 7))
>Partial : Symbol(Partial, Decl(mappedTypes2.ts, 0, 0))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
var partial: Partial<Shape> = {};
>partial : Symbol(partial, Decl(mappedTypes2.ts, 69, 7), Decl(mappedTypes2.ts, 70, 7), Decl(mappedTypes2.ts, 71, 7))
>Partial : Symbol(Partial, Decl(mappedTypes2.ts, 0, 0))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
}
function f3(shape: Shape) {
>f3 : Symbol(f3, Decl(mappedTypes2.ts, 72, 1))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 74, 12))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
const x = pick(shape, "name", "visible"); // { name: string, visible: boolean }
>x : Symbol(x, Decl(mappedTypes2.ts, 75, 9))
>pick : Symbol(pick, Decl(mappedTypes2.ts, 31, 48))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 74, 12))
}
function f4() {
>f4 : Symbol(f4, Decl(mappedTypes2.ts, 76, 1))
const rec = { foo: "hello", bar: "world", baz: "bye" };
>rec : Symbol(rec, Decl(mappedTypes2.ts, 79, 9))
>foo : Symbol(foo, Decl(mappedTypes2.ts, 79, 17))
>bar : Symbol(bar, Decl(mappedTypes2.ts, 79, 31))
>baz : Symbol(baz, Decl(mappedTypes2.ts, 79, 45))
const lengths = mapObject(rec, s => s.length); // { foo: number, bar: number, baz: number }
>lengths : Symbol(lengths, Decl(mappedTypes2.ts, 80, 9))
>mapObject : Symbol(mapObject, Decl(mappedTypes2.ts, 32, 78))
>rec : Symbol(rec, Decl(mappedTypes2.ts, 79, 9))
>s : Symbol(s, Decl(mappedTypes2.ts, 80, 34))
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(mappedTypes2.ts, 80, 34))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
function f5(shape: Shape) {
>f5 : Symbol(f5, Decl(mappedTypes2.ts, 81, 1))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 83, 12))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
const p = proxify(shape);
>p : Symbol(p, Decl(mappedTypes2.ts, 84, 9))
>proxify : Symbol(proxify, Decl(mappedTypes2.ts, 33, 109))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 83, 12))
let name = p.name.get();
>name : Symbol(name, Decl(mappedTypes2.ts, 85, 7))
>p.name.get : Symbol(get, Decl(mappedTypes2.ts, 17, 17))
>p.name : Symbol(name)
>p : Symbol(p, Decl(mappedTypes2.ts, 84, 9))
>name : Symbol(name)
>get : Symbol(get, Decl(mappedTypes2.ts, 17, 17))
p.visible.set(false);
>p.visible.set : Symbol(set, Decl(mappedTypes2.ts, 18, 13))
>p.visible : Symbol(visible)
>p : Symbol(p, Decl(mappedTypes2.ts, 84, 9))
>visible : Symbol(visible)
>set : Symbol(set, Decl(mappedTypes2.ts, 18, 13))
}
function f6(shape: DeepReadonly<Shape>) {
>f6 : Symbol(f6, Decl(mappedTypes2.ts, 87, 1))
>shape : Symbol(shape, Decl(mappedTypes2.ts, 89, 12))
>DeepReadonly : Symbol(DeepReadonly, Decl(mappedTypes2.ts, 24, 1))
>Shape : Symbol(Shape, Decl(mappedTypes2.ts, 34, 48))
let name = shape.name; // DeepReadonly<string>
>name : Symbol(name, Decl(mappedTypes2.ts, 90, 7))
>shape.name : Symbol(name)
>shape : Symbol(shape, Decl(mappedTypes2.ts, 89, 12))
>name : Symbol(name)
let length = name.length; // DeepReadonly<number>
>length : Symbol(length, Decl(mappedTypes2.ts, 91, 7))
>name.length : Symbol(length)
>name : Symbol(name, Decl(mappedTypes2.ts, 90, 7))
>length : Symbol(length)
let toString = length.toString; // DeepReadonly<(radix?: number) => string>
>toString : Symbol(toString, Decl(mappedTypes2.ts, 92, 7))
>length.toString : Symbol(toString)
>length : Symbol(length, Decl(mappedTypes2.ts, 91, 7))
>toString : Symbol(toString)
}

View file

@ -0,0 +1,353 @@
=== tests/cases/conformance/types/mapped/mappedTypes2.ts ===
type Partial<T> = {
>Partial : Partial<T>
>T : T
[P in keyof T]?: T[P];
>P : P
>T : T
>T : T
>P : P
};
type Readonly<T> = {
>Readonly : Readonly<T>
>T : T
readonly [P in keyof T]: T[P];
>P : P
>T : T
>T : T
>P : P
};
type Pick<T, K extends keyof T> = {
>Pick : Pick<T, K>
>T : T
>K : K
>T : T
[P in K]: T[P];
>P : P
>K : K
>T : T
>P : P
}
type Record<K extends string | number, T> = {
>Record : Record<K, T>
>K : K
>T : T
[_ in K]: T;
>_ : _
>K : K
>T : T
}
type Proxy<T> = {
>Proxy : Proxy<T>
>T : T
get(): T;
>get : () => T
>T : T
set(value: T): void;
>set : (value: T) => void
>value : T
>T : T
}
type Proxify<T> = {
>Proxify : Proxify<T>
>T : T
[P in keyof T]: Proxy<T[P]>;
>P : P
>T : T
>Proxy : Proxy<T>
>T : T
>P : P
}
type DeepReadonly<T> = {
>DeepReadonly : DeepReadonly<T>
>T : T
readonly [P in keyof T]: DeepReadonly<T[P]>;
>P : P
>T : T
>DeepReadonly : DeepReadonly<T>
>T : T
>P : P
};
declare function assign<T>(obj: T, props: Partial<T>): void;
>assign : <T>(obj: T, props: Partial<T>) => void
>T : T
>obj : T
>T : T
>props : Partial<T>
>Partial : Partial<T>
>T : T
declare function freeze<T>(obj: T): Readonly<T>;
>freeze : <T>(obj: T) => Readonly<T>
>T : T
>obj : T
>T : T
>Readonly : Readonly<T>
>T : T
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
>pick : <T, K extends keyof T>(obj: T, ...keys: K[]) => Pick<T, K>
>T : T
>K : K
>T : T
>obj : T
>T : T
>keys : K[]
>K : K
>Pick : Pick<T, K>
>T : T
>K : K
declare function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;
>mapObject : <K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U) => Record<K, U>
>K : K
>T : T
>U : U
>obj : Record<K, T>
>Record : Record<K, T>
>K : K
>T : T
>f : (x: T) => U
>x : T
>T : T
>U : U
>Record : Record<K, T>
>K : K
>U : U
declare function proxify<T>(obj: T): Proxify<T>;
>proxify : <T>(obj: T) => Proxify<T>
>T : T
>obj : T
>T : T
>Proxify : Proxify<T>
>T : T
interface Shape {
>Shape : Shape
name: string;
>name : string
width: number;
>width : number
height: number;
>height : number
visible: boolean;
>visible : boolean
}
interface PartialShape {
>PartialShape : PartialShape
name?: string;
>name : string | undefined
width?: number;
>width : number | undefined
height?: number;
>height : number | undefined
visible?: boolean;
>visible : boolean | undefined
}
interface ReadonlyShape {
>ReadonlyShape : ReadonlyShape
readonly name: string;
>name : string
readonly width: number;
>width : number
readonly height: number;
>height : number
readonly visible: boolean;
>visible : boolean
}
function f0(s1: Shape, s2: Shape) {
>f0 : (s1: Shape, s2: Shape) => void
>s1 : Shape
>Shape : Shape
>s2 : Shape
>Shape : Shape
assign(s1, { name: "circle" });
>assign(s1, { name: "circle" }) : void
>assign : <T>(obj: T, props: Partial<T>) => void
>s1 : Shape
>{ name: "circle" } : { name: string; }
>name : string
>"circle" : "circle"
assign(s2, { width: 10, height: 20 });
>assign(s2, { width: 10, height: 20 }) : void
>assign : <T>(obj: T, props: Partial<T>) => void
>s2 : Shape
>{ width: 10, height: 20 } : { width: number; height: number; }
>width : number
>10 : 10
>height : number
>20 : 20
}
function f1(shape: Shape) {
>f1 : (shape: Shape) => void
>shape : Shape
>Shape : Shape
var frozen: ReadonlyShape;
>frozen : ReadonlyShape
>ReadonlyShape : ReadonlyShape
var frozen: Readonly<Shape>;
>frozen : ReadonlyShape
>Readonly : Readonly<T>
>Shape : Shape
var frozen = freeze(shape);
>frozen : ReadonlyShape
>freeze(shape) : Readonly<Shape>
>freeze : <T>(obj: T) => Readonly<T>
>shape : Shape
}
function f2(shape: Shape) {
>f2 : (shape: Shape) => void
>shape : Shape
>Shape : Shape
var partial: PartialShape;
>partial : PartialShape
>PartialShape : PartialShape
var partial: Partial<Shape>;
>partial : PartialShape
>Partial : Partial<T>
>Shape : Shape
var partial: Partial<Shape> = {};
>partial : PartialShape
>Partial : Partial<T>
>Shape : Shape
>{} : {}
}
function f3(shape: Shape) {
>f3 : (shape: Shape) => void
>shape : Shape
>Shape : Shape
const x = pick(shape, "name", "visible"); // { name: string, visible: boolean }
>x : Pick<Shape, "name" | "visible">
>pick(shape, "name", "visible") : Pick<Shape, "name" | "visible">
>pick : <T, K extends keyof T>(obj: T, ...keys: K[]) => Pick<T, K>
>shape : Shape
>"name" : "name"
>"visible" : "visible"
}
function f4() {
>f4 : () => void
const rec = { foo: "hello", bar: "world", baz: "bye" };
>rec : { foo: string; bar: string; baz: string; }
>{ foo: "hello", bar: "world", baz: "bye" } : { foo: string; bar: string; baz: string; }
>foo : string
>"hello" : "hello"
>bar : string
>"world" : "world"
>baz : string
>"bye" : "bye"
const lengths = mapObject(rec, s => s.length); // { foo: number, bar: number, baz: number }
>lengths : Record<"foo" | "bar" | "baz", number>
>mapObject(rec, s => s.length) : Record<"foo" | "bar" | "baz", number>
>mapObject : <K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U) => Record<K, U>
>rec : { foo: string; bar: string; baz: string; }
>s => s.length : (s: string) => number
>s : string
>s.length : number
>s : string
>length : number
}
function f5(shape: Shape) {
>f5 : (shape: Shape) => void
>shape : Shape
>Shape : Shape
const p = proxify(shape);
>p : Proxify<Shape>
>proxify(shape) : Proxify<Shape>
>proxify : <T>(obj: T) => Proxify<T>
>shape : Shape
let name = p.name.get();
>name : string
>p.name.get() : string
>p.name.get : () => string
>p.name : Proxy<string>
>p : Proxify<Shape>
>name : Proxy<string>
>get : () => string
p.visible.set(false);
>p.visible.set(false) : void
>p.visible.set : (value: boolean) => void
>p.visible : Proxy<boolean>
>p : Proxify<Shape>
>visible : Proxy<boolean>
>set : (value: boolean) => void
>false : false
}
function f6(shape: DeepReadonly<Shape>) {
>f6 : (shape: DeepReadonly<Shape>) => void
>shape : DeepReadonly<Shape>
>DeepReadonly : DeepReadonly<T>
>Shape : Shape
let name = shape.name; // DeepReadonly<string>
>name : DeepReadonly<string>
>shape.name : DeepReadonly<string>
>shape : DeepReadonly<Shape>
>name : DeepReadonly<string>
let length = name.length; // DeepReadonly<number>
>length : DeepReadonly<number>
>name.length : DeepReadonly<number>
>name : DeepReadonly<string>
>length : DeepReadonly<number>
let toString = length.toString; // DeepReadonly<(radix?: number) => string>
>toString : DeepReadonly<(radix?: number | undefined) => string>
>length.toString : DeepReadonly<(radix?: number | undefined) => string>
>length : DeepReadonly<number>
>toString : DeepReadonly<(radix?: number | undefined) => string>
}

View file

@ -0,0 +1,84 @@
//// [mappedTypes3.ts]
class Box<P> {
value: P;
}
type Boxified<T> = {
[K in keyof T]: Box<T[K]>;
}
declare function boxify<T>(obj: T): Boxified<T>;
declare function unboxify<T>(obj: Boxified<T>): T;
interface Bacon {
isPerfect: boolean;
weight: number;
}
interface BoxifiedBacon {
isPerfect: Box<boolean>;
weight: Box<number>;
}
function f1(b: Bacon) {
let bb = boxify(b);
let isPerfect = bb.isPerfect.value;
let weight = bb.weight.value;
}
function f2(bb: Boxified<Bacon>) {
let b = unboxify(bb); // Infer Bacon for T
let bool = b.isPerfect;
let weight = b.weight;
}
function f3(bb: BoxifiedBacon) {
let b = unboxify<Bacon>(bb); // Explicit type parameter required
let bool = b.isPerfect;
let weight = bb.weight;
}
//// [mappedTypes3.js]
var Box = (function () {
function Box() {
}
return Box;
}());
function f1(b) {
var bb = boxify(b);
var isPerfect = bb.isPerfect.value;
var weight = bb.weight.value;
}
function f2(bb) {
var b = unboxify(bb); // Infer Bacon for T
var bool = b.isPerfect;
var weight = b.weight;
}
function f3(bb) {
var b = unboxify(bb); // Explicit type parameter required
var bool = b.isPerfect;
var weight = bb.weight;
}
//// [mappedTypes3.d.ts]
declare class Box<P> {
value: P;
}
declare type Boxified<T> = {
[K in keyof T]: Box<T[K]>;
};
declare function boxify<T>(obj: T): Boxified<T>;
declare function unboxify<T>(obj: Boxified<T>): T;
interface Bacon {
isPerfect: boolean;
weight: number;
}
interface BoxifiedBacon {
isPerfect: Box<boolean>;
weight: Box<number>;
}
declare function f1(b: Bacon): void;
declare function f2(bb: Boxified<Bacon>): void;
declare function f3(bb: BoxifiedBacon): void;

View file

@ -0,0 +1,135 @@
=== tests/cases/conformance/types/mapped/mappedTypes3.ts ===
class Box<P> {
>Box : Symbol(Box, Decl(mappedTypes3.ts, 0, 0))
>P : Symbol(P, Decl(mappedTypes3.ts, 1, 10))
value: P;
>value : Symbol(Box.value, Decl(mappedTypes3.ts, 1, 14))
>P : Symbol(P, Decl(mappedTypes3.ts, 1, 10))
}
type Boxified<T> = {
>Boxified : Symbol(Boxified, Decl(mappedTypes3.ts, 3, 1))
>T : Symbol(T, Decl(mappedTypes3.ts, 5, 14))
[K in keyof T]: Box<T[K]>;
>K : Symbol(K, Decl(mappedTypes3.ts, 6, 5))
>T : Symbol(T, Decl(mappedTypes3.ts, 5, 14))
>Box : Symbol(Box, Decl(mappedTypes3.ts, 0, 0))
>T : Symbol(T, Decl(mappedTypes3.ts, 5, 14))
>K : Symbol(K, Decl(mappedTypes3.ts, 6, 5))
}
declare function boxify<T>(obj: T): Boxified<T>;
>boxify : Symbol(boxify, Decl(mappedTypes3.ts, 7, 1))
>T : Symbol(T, Decl(mappedTypes3.ts, 9, 24))
>obj : Symbol(obj, Decl(mappedTypes3.ts, 9, 27))
>T : Symbol(T, Decl(mappedTypes3.ts, 9, 24))
>Boxified : Symbol(Boxified, Decl(mappedTypes3.ts, 3, 1))
>T : Symbol(T, Decl(mappedTypes3.ts, 9, 24))
declare function unboxify<T>(obj: Boxified<T>): T;
>unboxify : Symbol(unboxify, Decl(mappedTypes3.ts, 9, 48))
>T : Symbol(T, Decl(mappedTypes3.ts, 10, 26))
>obj : Symbol(obj, Decl(mappedTypes3.ts, 10, 29))
>Boxified : Symbol(Boxified, Decl(mappedTypes3.ts, 3, 1))
>T : Symbol(T, Decl(mappedTypes3.ts, 10, 26))
>T : Symbol(T, Decl(mappedTypes3.ts, 10, 26))
interface Bacon {
>Bacon : Symbol(Bacon, Decl(mappedTypes3.ts, 10, 50))
isPerfect: boolean;
>isPerfect : Symbol(Bacon.isPerfect, Decl(mappedTypes3.ts, 12, 17))
weight: number;
>weight : Symbol(Bacon.weight, Decl(mappedTypes3.ts, 13, 23))
}
interface BoxifiedBacon {
>BoxifiedBacon : Symbol(BoxifiedBacon, Decl(mappedTypes3.ts, 15, 1))
isPerfect: Box<boolean>;
>isPerfect : Symbol(BoxifiedBacon.isPerfect, Decl(mappedTypes3.ts, 17, 25))
>Box : Symbol(Box, Decl(mappedTypes3.ts, 0, 0))
weight: Box<number>;
>weight : Symbol(BoxifiedBacon.weight, Decl(mappedTypes3.ts, 18, 28))
>Box : Symbol(Box, Decl(mappedTypes3.ts, 0, 0))
}
function f1(b: Bacon) {
>f1 : Symbol(f1, Decl(mappedTypes3.ts, 20, 1))
>b : Symbol(b, Decl(mappedTypes3.ts, 22, 12))
>Bacon : Symbol(Bacon, Decl(mappedTypes3.ts, 10, 50))
let bb = boxify(b);
>bb : Symbol(bb, Decl(mappedTypes3.ts, 23, 7))
>boxify : Symbol(boxify, Decl(mappedTypes3.ts, 7, 1))
>b : Symbol(b, Decl(mappedTypes3.ts, 22, 12))
let isPerfect = bb.isPerfect.value;
>isPerfect : Symbol(isPerfect, Decl(mappedTypes3.ts, 24, 7))
>bb.isPerfect.value : Symbol(Box.value, Decl(mappedTypes3.ts, 1, 14))
>bb.isPerfect : Symbol(isPerfect)
>bb : Symbol(bb, Decl(mappedTypes3.ts, 23, 7))
>isPerfect : Symbol(isPerfect)
>value : Symbol(Box.value, Decl(mappedTypes3.ts, 1, 14))
let weight = bb.weight.value;
>weight : Symbol(weight, Decl(mappedTypes3.ts, 25, 7))
>bb.weight.value : Symbol(Box.value, Decl(mappedTypes3.ts, 1, 14))
>bb.weight : Symbol(weight)
>bb : Symbol(bb, Decl(mappedTypes3.ts, 23, 7))
>weight : Symbol(weight)
>value : Symbol(Box.value, Decl(mappedTypes3.ts, 1, 14))
}
function f2(bb: Boxified<Bacon>) {
>f2 : Symbol(f2, Decl(mappedTypes3.ts, 26, 1))
>bb : Symbol(bb, Decl(mappedTypes3.ts, 28, 12))
>Boxified : Symbol(Boxified, Decl(mappedTypes3.ts, 3, 1))
>Bacon : Symbol(Bacon, Decl(mappedTypes3.ts, 10, 50))
let b = unboxify(bb); // Infer Bacon for T
>b : Symbol(b, Decl(mappedTypes3.ts, 29, 7))
>unboxify : Symbol(unboxify, Decl(mappedTypes3.ts, 9, 48))
>bb : Symbol(bb, Decl(mappedTypes3.ts, 28, 12))
let bool = b.isPerfect;
>bool : Symbol(bool, Decl(mappedTypes3.ts, 30, 7))
>b.isPerfect : Symbol(Bacon.isPerfect, Decl(mappedTypes3.ts, 12, 17))
>b : Symbol(b, Decl(mappedTypes3.ts, 29, 7))
>isPerfect : Symbol(Bacon.isPerfect, Decl(mappedTypes3.ts, 12, 17))
let weight = b.weight;
>weight : Symbol(weight, Decl(mappedTypes3.ts, 31, 7))
>b.weight : Symbol(Bacon.weight, Decl(mappedTypes3.ts, 13, 23))
>b : Symbol(b, Decl(mappedTypes3.ts, 29, 7))
>weight : Symbol(Bacon.weight, Decl(mappedTypes3.ts, 13, 23))
}
function f3(bb: BoxifiedBacon) {
>f3 : Symbol(f3, Decl(mappedTypes3.ts, 32, 1))
>bb : Symbol(bb, Decl(mappedTypes3.ts, 34, 12))
>BoxifiedBacon : Symbol(BoxifiedBacon, Decl(mappedTypes3.ts, 15, 1))
let b = unboxify<Bacon>(bb); // Explicit type parameter required
>b : Symbol(b, Decl(mappedTypes3.ts, 35, 7))
>unboxify : Symbol(unboxify, Decl(mappedTypes3.ts, 9, 48))
>Bacon : Symbol(Bacon, Decl(mappedTypes3.ts, 10, 50))
>bb : Symbol(bb, Decl(mappedTypes3.ts, 34, 12))
let bool = b.isPerfect;
>bool : Symbol(bool, Decl(mappedTypes3.ts, 36, 7))
>b.isPerfect : Symbol(Bacon.isPerfect, Decl(mappedTypes3.ts, 12, 17))
>b : Symbol(b, Decl(mappedTypes3.ts, 35, 7))
>isPerfect : Symbol(Bacon.isPerfect, Decl(mappedTypes3.ts, 12, 17))
let weight = bb.weight;
>weight : Symbol(weight, Decl(mappedTypes3.ts, 37, 7))
>bb.weight : Symbol(BoxifiedBacon.weight, Decl(mappedTypes3.ts, 18, 28))
>bb : Symbol(bb, Decl(mappedTypes3.ts, 34, 12))
>weight : Symbol(BoxifiedBacon.weight, Decl(mappedTypes3.ts, 18, 28))
}

View file

@ -0,0 +1,138 @@
=== tests/cases/conformance/types/mapped/mappedTypes3.ts ===
class Box<P> {
>Box : Box<P>
>P : P
value: P;
>value : P
>P : P
}
type Boxified<T> = {
>Boxified : Boxified<T>
>T : T
[K in keyof T]: Box<T[K]>;
>K : K
>T : T
>Box : Box<P>
>T : T
>K : K
}
declare function boxify<T>(obj: T): Boxified<T>;
>boxify : <T>(obj: T) => Boxified<T>
>T : T
>obj : T
>T : T
>Boxified : Boxified<T>
>T : T
declare function unboxify<T>(obj: Boxified<T>): T;
>unboxify : <T>(obj: Boxified<T>) => T
>T : T
>obj : Boxified<T>
>Boxified : Boxified<T>
>T : T
>T : T
interface Bacon {
>Bacon : Bacon
isPerfect: boolean;
>isPerfect : boolean
weight: number;
>weight : number
}
interface BoxifiedBacon {
>BoxifiedBacon : BoxifiedBacon
isPerfect: Box<boolean>;
>isPerfect : Box<boolean>
>Box : Box<P>
weight: Box<number>;
>weight : Box<number>
>Box : Box<P>
}
function f1(b: Bacon) {
>f1 : (b: Bacon) => void
>b : Bacon
>Bacon : Bacon
let bb = boxify(b);
>bb : Boxified<Bacon>
>boxify(b) : Boxified<Bacon>
>boxify : <T>(obj: T) => Boxified<T>
>b : Bacon
let isPerfect = bb.isPerfect.value;
>isPerfect : boolean
>bb.isPerfect.value : boolean
>bb.isPerfect : Box<boolean>
>bb : Boxified<Bacon>
>isPerfect : Box<boolean>
>value : boolean
let weight = bb.weight.value;
>weight : number
>bb.weight.value : number
>bb.weight : Box<number>
>bb : Boxified<Bacon>
>weight : Box<number>
>value : number
}
function f2(bb: Boxified<Bacon>) {
>f2 : (bb: Boxified<Bacon>) => void
>bb : Boxified<Bacon>
>Boxified : Boxified<T>
>Bacon : Bacon
let b = unboxify(bb); // Infer Bacon for T
>b : Bacon
>unboxify(bb) : Bacon
>unboxify : <T>(obj: Boxified<T>) => T
>bb : Boxified<Bacon>
let bool = b.isPerfect;
>bool : boolean
>b.isPerfect : boolean
>b : Bacon
>isPerfect : boolean
let weight = b.weight;
>weight : number
>b.weight : number
>b : Bacon
>weight : number
}
function f3(bb: BoxifiedBacon) {
>f3 : (bb: BoxifiedBacon) => void
>bb : BoxifiedBacon
>BoxifiedBacon : BoxifiedBacon
let b = unboxify<Bacon>(bb); // Explicit type parameter required
>b : Bacon
>unboxify<Bacon>(bb) : Bacon
>unboxify : <T>(obj: Boxified<T>) => T
>Bacon : Bacon
>bb : BoxifiedBacon
let bool = b.isPerfect;
>bool : boolean
>b.isPerfect : boolean
>b : Bacon
>isPerfect : boolean
let weight = bb.weight;
>weight : Box<number>
>bb.weight : Box<number>
>bb : BoxifiedBacon
>weight : Box<number>
}

View file

@ -1,4 +1,4 @@
tests/cases/compiler/noErrorTruncation.ts(10,7): error TS2322: Type '42' is not assignable to type '{ someLongOptionA: string; } | { someLongOptionB: string; } | { someLongOptionC: string; } | { someLongOptionD: string; } | { someLongOptionE: string; } | { someLongOptionF: string; }'.
tests/cases/compiler/noErrorTruncation.ts(10,7): error TS2322: Type '42' is not assignable to type 'SomeLongOptionA | SomeLongOptionB | SomeLongOptionC | SomeLongOptionD | SomeLongOptionE | SomeLongOptionF'.
==== tests/cases/compiler/noErrorTruncation.ts (1 errors) ====
@ -13,7 +13,7 @@ tests/cases/compiler/noErrorTruncation.ts(10,7): error TS2322: Type '42' is not
const x: SomeLongOptionA
~
!!! error TS2322: Type '42' is not assignable to type '{ someLongOptionA: string; } | { someLongOptionB: string; } | { someLongOptionC: string; } | { someLongOptionD: string; } | { someLongOptionE: string; } | { someLongOptionF: string; }'.
!!! error TS2322: Type '42' is not assignable to type 'SomeLongOptionA | SomeLongOptionB | SomeLongOptionC | SomeLongOptionD | SomeLongOptionE | SomeLongOptionF'.
| SomeLongOptionB
| SomeLongOptionC
| SomeLongOptionD

View file

@ -8,7 +8,7 @@ import { IEventSourcedEntity } from "./bar";
>IEventSourcedEntity : any
export type DomainEntityConstructor<TEntity extends IEventSourcedEntity> = { new(): TEntity; };
>DomainEntityConstructor : new () => TEntity
>DomainEntityConstructor : DomainEntityConstructor<TEntity>
>TEntity : TEntity
>IEventSourcedEntity : IEventSourcedEntity
>TEntity : TEntity

View file

@ -1,7 +1,7 @@
=== tests/cases/compiler/typeAliasDeclarationEmit2.ts ===
export type A<a> = { value: a };
>A : { value: a; }
>A : A<a>
>a : a
>value : a
>a : a

View file

@ -104,7 +104,7 @@ var x9: T9;
>T9 : T9
type T10 = { x: number };
>T10 : { x: number; }
>T10 : T10
>x : number
var x10: { x: number };
@ -113,17 +113,17 @@ var x10: { x: number };
var x10: T10;
>x10 : { x: number; }
>T10 : { x: number; }
>T10 : T10
type T11 = { new(): boolean };
>T11 : new () => boolean
>T11 : T11
var x11: { new(): boolean };
>x11 : new () => boolean
var x11: T11;
>x11 : new () => boolean
>T11 : new () => boolean
>T11 : T11
interface I13 { x: string };
>I13 : I13

View file

@ -11,7 +11,7 @@ type TreeNode = {
}
type TreeNodeMiddleman = {
>TreeNodeMiddleman : { name: string; parent: TreeNode; }
>TreeNodeMiddleman : TreeNodeMiddleman
name: string;
>name : string
@ -22,17 +22,17 @@ type TreeNodeMiddleman = {
}
var nodes: TreeNodeMiddleman[];
>nodes : { name: string; parent: TreeNode; }[]
>TreeNodeMiddleman : { name: string; parent: TreeNode; }
>nodes : TreeNodeMiddleman[]
>TreeNodeMiddleman : TreeNodeMiddleman
nodes.map(n => n.name);
>nodes.map(n => n.name) : string[]
>nodes.map : { <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): U[]; }
>nodes : { name: string; parent: TreeNode; }[]
>map : { <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U, U]; <U>(this: [{ name: string; parent: TreeNode; }, { name: string; parent: TreeNode; }], callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: { name: string; parent: TreeNode; }, index: number, array: { name: string; parent: TreeNode; }[]) => U, thisArg?: any): U[]; }
>n => n.name : (n: { name: string; parent: TreeNode; }) => string
>n : { name: string; parent: TreeNode; }
>nodes.map : { <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): U[]; }
>nodes : TreeNodeMiddleman[]
>map : { <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U, U]; <U>(this: [TreeNodeMiddleman, TreeNodeMiddleman], callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): [U, U]; <U>(callbackfn: (value: TreeNodeMiddleman, index: number, array: TreeNodeMiddleman[]) => U, thisArg?: any): U[]; }
>n => n.name : (n: TreeNodeMiddleman) => string
>n : TreeNodeMiddleman
>n.name : string
>n : { name: string; parent: TreeNode; }
>n : TreeNodeMiddleman
>name : string

View file

@ -1,18 +1,18 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsPrimitiveIntersection.ts ===
type Tag = {__tag: any};
>Tag : { __tag: any; }
>Tag : Tag
>__tag : any
declare function isNonBlank(value: string) : value is (string & Tag);
>isNonBlank : (value: string) => value is string & { __tag: any; }
>isNonBlank : (value: string) => value is string & Tag
>value : string
>value : any
>Tag : { __tag: any; }
>Tag : Tag
declare function doThis(value: string & Tag): void;
>doThis : (value: string & { __tag: any; }) => void
>value : string & { __tag: any; }
>Tag : { __tag: any; }
>doThis : (value: string & Tag) => void
>value : string & Tag
>Tag : Tag
declare function doThat(value: string) : void;
>doThat : (value: string) => void
@ -23,13 +23,13 @@ let value: string;
if (isNonBlank(value)) {
>isNonBlank(value) : boolean
>isNonBlank : (value: string) => value is string & { __tag: any; }
>isNonBlank : (value: string) => value is string & Tag
>value : string
doThis(value);
>doThis(value) : void
>doThis : (value: string & { __tag: any; }) => void
>value : string & { __tag: any; }
>doThis : (value: string & Tag) => void
>value : string & Tag
} else {
doThat(value);

View file

@ -0,0 +1,62 @@
// @strictNullChecks: true
// @declaration: true
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string | number, T> = {
[_ in K]: T;
}
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface Named {
name: string;
}
interface Point {
x: number;
y: number;
}
type T00 = { [P in P]: string }; // Error
type T01 = { [P in Date]: number }; // Error
type T02 = Record<Date, number>; // Error
type T10 = Pick<Shape, "name">;
type T11 = Pick<Shape, "foo">; // Error
type T12 = Pick<Shape, "name" | "foo">; // Error
type T13 = Pick<Shape, keyof Named>;
type T14 = Pick<Shape, keyof Point>; // Error
type T15 = Pick<Shape, never>;
type T16 = Pick<Shape, undefined>; // Error
function f1<T>(x: T) {
let y: Pick<Shape, T>; // Error
}
function f2<T extends string | number>(x: T) {
let y: Pick<Shape, T>; // Error
}
function f3<T extends keyof Shape>(x: T) {
let y: Pick<Shape, T>;
}
function f4<T extends keyof Named>(x: T) {
let y: Pick<Shape, T>;
}

View file

@ -0,0 +1,44 @@
// @strictNullChecks: true
// @declaration: true
type Item = { a: string, b: number, c: boolean };
type T00 = { [P in "x" | "y"]: number };
type T01 = { [P in "x" | "y"]: P };
type T02 = { [P in "a" | "b"]: Item[P]; }
type T03 = { [P in keyof Item]: Date };
type T10 = { [P in keyof Item]: Item[P] };
type T11 = { [P in keyof Item]?: Item[P] };
type T12 = { readonly [P in keyof Item]: Item[P] };
type T13 = { readonly [P in keyof Item]?: Item[P] };
type T20 = { [P in keyof Item]: Item[P] | null };
type T21 = { [P in keyof Item]: Array<Item[P]> };
type T30 = { [P in keyof any]: void };
type T31 = { [P in keyof string]: void };
type T32 = { [P in keyof number]: void };
type T33 = { [P in keyof boolean]: void };
type T34 = { [P in keyof undefined]: void };
type T35 = { [P in keyof null]: void };
type T36 = { [P in keyof void]: void };
type T37 = { [P in keyof symbol]: void };
type T38 = { [P in keyof never]: void };
type T40 = { [P in string]: void };
type T41 = { [P in number]: void };
type T42 = { [P in string | number]: void };
type T43 = { [P in "a" | "b" | 0 | 1]: void };
type T44 = { [P in "a" | "b" | "0" | "1"]: void };
type T45 = { [P in "a" | "b" | "0" | "1" | 0 | 1]: void };
type T46 = { [P in number | "a" | "b" | 0 | 1]: void };
type T47 = { [P in string | number | "a" | "b" | 0 | 1]: void };
declare function f1<T1>(): { [P in keyof T1]: void };
declare function f2<T1 extends string>(): { [P in keyof T1]: void };
declare function f3<T1 extends number>(): { [P in keyof T1]: void };
let x1 = f1();
let x2 = f2();
let x3 = f3();

View file

@ -0,0 +1,96 @@
// @strictNullChecks: true
// @declaration: true
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string | number, T> = {
[_ in K]: T;
}
type Proxy<T> = {
get(): T;
set(value: T): void;
}
type Proxify<T> = {
[P in keyof T]: Proxy<T[P]>;
}
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
declare function assign<T>(obj: T, props: Partial<T>): void;
declare function freeze<T>(obj: T): Readonly<T>;
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
declare function mapObject<K extends string | number, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>;
declare function proxify<T>(obj: T): Proxify<T>;
interface Shape {
name: string;
width: number;
height: number;
visible: boolean;
}
interface PartialShape {
name?: string;
width?: number;
height?: number;
visible?: boolean;
}
interface ReadonlyShape {
readonly name: string;
readonly width: number;
readonly height: number;
readonly visible: boolean;
}
function f0(s1: Shape, s2: Shape) {
assign(s1, { name: "circle" });
assign(s2, { width: 10, height: 20 });
}
function f1(shape: Shape) {
var frozen: ReadonlyShape;
var frozen: Readonly<Shape>;
var frozen = freeze(shape);
}
function f2(shape: Shape) {
var partial: PartialShape;
var partial: Partial<Shape>;
var partial: Partial<Shape> = {};
}
function f3(shape: Shape) {
const x = pick(shape, "name", "visible"); // { name: string, visible: boolean }
}
function f4() {
const rec = { foo: "hello", bar: "world", baz: "bye" };
const lengths = mapObject(rec, s => s.length); // { foo: number, bar: number, baz: number }
}
function f5(shape: Shape) {
const p = proxify(shape);
let name = p.name.get();
p.visible.set(false);
}
function f6(shape: DeepReadonly<Shape>) {
let name = shape.name; // DeepReadonly<string>
let length = name.length; // DeepReadonly<number>
let toString = length.toString; // DeepReadonly<(radix?: number) => string>
}

View file

@ -0,0 +1,40 @@
// @declaration: true
class Box<P> {
value: P;
}
type Boxified<T> = {
[K in keyof T]: Box<T[K]>;
}
declare function boxify<T>(obj: T): Boxified<T>;
declare function unboxify<T>(obj: Boxified<T>): T;
interface Bacon {
isPerfect: boolean;
weight: number;
}
interface BoxifiedBacon {
isPerfect: Box<boolean>;
weight: Box<number>;
}
function f1(b: Bacon) {
let bb = boxify(b);
let isPerfect = bb.isPerfect.value;
let weight = bb.weight.value;
}
function f2(bb: Boxified<Bacon>) {
let b = unboxify(bb); // Infer Bacon for T
let bool = b.isPerfect;
let weight = b.weight;
}
function f3(bb: BoxifiedBacon) {
let b = unboxify<Bacon>(bb); // Explicit type parameter required
let bool = b.isPerfect;
let weight = bb.weight;
}