Merge pull request #12546 from Microsoft/mergeMaster1128

Merge master1128
This commit is contained in:
Mohamed Hegazy 2016-11-28 16:44:22 -08:00 committed by GitHub
commit 6e2db6c771
37 changed files with 2668 additions and 518 deletions

View File

@ -3205,7 +3205,7 @@ namespace ts {
// right hand expression is of a type parameter type.
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
const indexType = getIndexType(checkNonNullExpression((<ForInStatement>declaration.parent.parent).expression));
return indexType.flags & TypeFlags.Index ? indexType : stringType;
return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? indexType : stringType;
}
if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
@ -4494,7 +4494,6 @@ namespace ts {
function resolveMappedTypeMembers(type: MappedType) {
const members: SymbolTable = createMap<Symbol>();
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
// Resolve upfront such that recursive references see an empty object type.
setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined);
// In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
@ -4529,16 +4528,8 @@ namespace ts {
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);
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
}
function getTypeParameterFromMappedType(type: MappedType) {
@ -5637,6 +5628,7 @@ namespace ts {
containsString?: boolean;
containsNumber?: boolean;
containsStringOrNumberLiteral?: boolean;
unionIndex?: number;
}
function binarySearchTypes(types: Type[], type: Type): number {
@ -5831,6 +5823,9 @@ namespace ts {
typeSet.containsAny = true;
}
else if (!(type.flags & TypeFlags.Never) && (strictNullChecks || !(type.flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
if (type.flags & TypeFlags.Union && typeSet.unionIndex === undefined) {
typeSet.unionIndex = typeSet.length;
}
typeSet.push(type);
}
}
@ -5857,15 +5852,6 @@ namespace ts {
if (types.length === 0) {
return emptyObjectType;
}
for (let i = 0; i < types.length; i++) {
const type = types[i];
if (type.flags & TypeFlags.Union) {
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
return getUnionType(map((<UnionType>type).types, t => getIntersectionType(replaceElement(types, i, t))),
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
}
}
const typeSet = [] as TypeSet;
addTypesToIntersection(typeSet, types);
if (typeSet.containsAny) {
@ -5874,6 +5860,14 @@ namespace ts {
if (typeSet.length === 1) {
return typeSet[0];
}
const unionIndex = typeSet.unionIndex;
if (unionIndex !== undefined) {
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
const unionType = <UnionType>typeSet[unionIndex];
return getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
}
const id = getTypeListId(typeSet);
let type = intersectionTypes[id];
if (!type) {
@ -5920,6 +5914,11 @@ namespace ts {
getLiteralTypeFromPropertyNames(type);
}
function getIndexTypeOrString(type: Type): Type {
const indexType = getIndexType(type);
return indexType !== neverType ? indexType : stringType;
}
function getTypeFromTypeOperatorNode(node: TypeOperatorNode) {
const links = getNodeLinks(node);
if (!links.resolvedType) {
@ -6018,8 +6017,7 @@ namespace ts {
// meaningfully access the properties of the object type. In those cases, we first check that the
// index type is assignable to 'keyof T' for the object type.
if (accessNode) {
const keyType = indexType.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>indexType) || emptyObjectType : indexType;
if (!isTypeAssignableTo(keyType, getIndexType(objectType))) {
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
return unknownType;
}
@ -8425,7 +8423,7 @@ namespace ts {
// results for union and intersection types for performance reasons.
function couldContainTypeParameters(type: Type): boolean {
const objectFlags = getObjectFlags(type);
return !!(type.flags & TypeFlags.TypeParameter ||
return !!(type.flags & (TypeFlags.TypeParameter | TypeFlags.IndexedAccess) ||
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 ||
@ -8443,8 +8441,57 @@ namespace ts {
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
}
function inferTypes(context: InferenceContext, originalSource: Type, originalTarget: Type) {
const typeParameters = context.signature.typeParameters;
// Infer a suitable input type for an isomorphic mapped type { [P in keyof T]: X }. We construct
// an object type with the same set of properties as the source type, where the type of each
// property is computed by inferring from the source property type to X for a synthetic type
// parameter T[P] (i.e. we treat the type T[P] as the type parameter we're inferring for).
function inferTypeForIsomorphicMappedType(source: Type, target: MappedType): Type {
if (!isMappableType(source)) {
return source;
}
const typeParameter = getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
const typeParameterArray = [typeParameter];
const typeInferences = createTypeInferencesObject();
const typeInferencesArray = [typeInferences];
const templateType = getTemplateTypeFromMappedType(target);
const properties = getPropertiesOfType(source);
const members = createSymbolTable(properties);
let hasInferredTypes = false;
for (const prop of properties) {
const inferredPropType = inferTargetType(getTypeOfSymbol(prop));
if (inferredPropType) {
const inferredProp = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | prop.flags & SymbolFlags.Optional, prop.name);
inferredProp.declarations = prop.declarations;
inferredProp.type = inferredPropType;
inferredProp.isReadonly = isReadonlySymbol(prop);
members[prop.name] = inferredProp;
hasInferredTypes = true;
}
}
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
if (indexInfo) {
const inferredIndexType = inferTargetType(indexInfo.type);
if (inferredIndexType) {
indexInfo = createIndexInfo(inferredIndexType, indexInfo.isReadonly);
hasInferredTypes = true;
}
}
return hasInferredTypes ? createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined) : source;
function inferTargetType(sourceType: Type): Type {
typeInferences.primary = undefined;
typeInferences.secondary = undefined;
inferTypes(typeParameterArray, typeInferencesArray, sourceType, templateType);
const inferences = typeInferences.primary || typeInferences.secondary;
return inferences && getUnionType(inferences, /*subtypeReduction*/ true);
}
}
function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) {
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
}
function inferTypes(typeParameters: Type[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
let sourceStack: Type[];
let targetStack: Type[];
let depth = 0;
@ -8512,7 +8559,7 @@ namespace ts {
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
}
}
if (target.flags & TypeFlags.TypeParameter) {
if (target.flags & (TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {
// If target is a type parameter, make an inference, unless the source type contains
// the anyFunctionType (the wildcard type that's used to avoid contextually typing functions).
// Because the anyFunctionType is internal, it should not be exposed to the user by adding
@ -8524,7 +8571,7 @@ namespace ts {
}
for (let i = 0; i < typeParameters.length; i++) {
if (target === typeParameters[i]) {
const inferences = context.inferences[i];
const inferences = typeInferences[i];
if (!inferences.isFixed) {
// Any inferences that are made to a type parameter in a union type are inferior
// to inferences made to a flat (non-union) type. This is because if we infer to
@ -8538,7 +8585,7 @@ namespace ts {
if (!contains(candidates, source)) {
candidates.push(source);
}
if (!isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
inferences.topLevel = false;
}
}
@ -8586,19 +8633,6 @@ 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)) {
@ -8619,15 +8653,39 @@ namespace ts {
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
inferFromObjectTypes(source, target);
depth--;
}
}
}
function inferFromObjectTypes(source: Type, target: Type) {
if (getObjectFlags(target) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
if (constraintType.flags & TypeFlags.Index) {
// We're inferring from some source type S to an isomorphic mapped type { [P in keyof T]: X },
// where T is a type parameter. Use inferTypeForIsomorphicMappedType to infer a suitable source
// type and then infer from that type to T.
const index = indexOf(typeParameters, (<IndexType>constraintType).type);
if (index >= 0 && !typeInferences[index].isFixed) {
inferFromTypes(inferTypeForIsomorphicMappedType(source, <MappedType>target), typeParameters[index]);
}
return;
}
if (constraintType.flags & TypeFlags.TypeParameter) {
// We're inferring from some source type S to a mapped type { [P in T]: X }, where T is a type
// parameter. Infer from 'keyof S' to T and infer from a union of each property type in S to X.
inferFromTypes(getIndexType(source), constraintType);
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
}
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
}
function inferFromProperties(source: Type, target: Type) {
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {
@ -12458,7 +12516,7 @@ namespace ts {
const context = createInferenceContext(signature, /*inferUnionTypes*/ true);
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
inferTypes(context, instantiateType(source, contextualMapper), target);
inferTypesWithContext(context, instantiateType(source, contextualMapper), target);
});
return getSignatureInstantiation(signature, getInferredTypes(context));
}
@ -12493,7 +12551,7 @@ namespace ts {
if (thisType) {
const thisArgumentNode = getThisArgumentOfCall(node);
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
inferTypes(context, thisArgumentType, thisType);
inferTypesWithContext(context, thisArgumentType, thisType);
}
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
@ -12515,7 +12573,7 @@ namespace ts {
argType = checkExpressionWithContextualType(arg, paramType, mapper);
}
inferTypes(context, argType, paramType);
inferTypesWithContext(context, argType, paramType);
}
}
@ -12530,7 +12588,7 @@ namespace ts {
if (excludeArgument[i] === false) {
const arg = args[i];
const paramType = getTypeAtPosition(signature, i);
inferTypes(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
inferTypesWithContext(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
}
}
}
@ -13617,7 +13675,7 @@ namespace ts {
for (let i = 0; i < len; i++) {
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
if (declaration.type) {
inferTypes(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
inferTypesWithContext(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
}
}
}
@ -13703,7 +13761,7 @@ namespace ts {
// T in the second overload so that we do not infer Base as a candidate for T
// (inferring Base would make type argument inference inconsistent between the two
// overloads).
inferTypes(mapper.context, links.type, instantiateType(contextualType, mapper));
inferTypesWithContext(mapper.context, links.type, instantiateType(contextualType, mapper));
}
}
@ -13839,7 +13897,7 @@ namespace ts {
if (!switchTypes.length) {
return false;
}
return eachTypeContainedIn(type, switchTypes);
return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes);
}
function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
@ -14275,7 +14333,7 @@ namespace ts {
// The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
// and the right operand to be of type Any, an object type, or a type parameter type.
// The result is always of the Boolean primitive type.
if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
if (!(isTypeComparableTo(leftType, stringType) || isTypeOfKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) {
error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
}
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {
@ -17166,6 +17224,7 @@ namespace ts {
// Grammar checking
checkGrammarForInOrForOfStatement(node);
const rightType = checkNonNullExpression(node.expression);
// TypeScript 1.0 spec (April 2014): 5.4
// In a 'for-in' statement of the form
// for (let VarDecl in Expr) Statement
@ -17176,7 +17235,6 @@ namespace ts {
if (variable && isBindingPattern(variable.name)) {
error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
}
checkForInOrForOfVariableDeclaration(node);
}
else {
@ -17189,7 +17247,7 @@ namespace ts {
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
}
else if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike)) {
else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) {
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
}
else {
@ -17198,7 +17256,6 @@ namespace ts {
}
}
const rightType = checkNonNullExpression(node.expression);
// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
// in this case error about missing name is already reported - do not report extra one
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {

View File

@ -2558,6 +2558,8 @@ namespace ts {
case SyntaxKind.OpenBraceToken:
case SyntaxKind.OpenBracketToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.BarToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.NewKeyword:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
@ -2617,6 +2619,7 @@ namespace ts {
}
function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode {
parseOptional(operator);
let type = parseConstituentType();
if (token() === operator) {
const types = createNodeArray<TypeNode>([type], type.pos);

View File

@ -1353,13 +1353,13 @@ namespace ts {
// __metadata("design:type", Function),
// __metadata("design:paramtypes", [Object]),
// __metadata("design:returntype", void 0)
// ], C.prototype, "method", undefined);
// ], C.prototype, "method", null);
//
// The emit for an accessor is:
//
// __decorate([
// dec
// ], C.prototype, "accessor", undefined);
// ], C.prototype, "accessor", null);
//
// The emit for a property is:
//

View File

@ -0,0 +1,39 @@
//// [exhaustiveSwitchWithWideningLiteralTypes.ts]
// Repro from #12529
class A {
readonly kind = "A"; // (property) A.kind: "A"
}
class B {
readonly kind = "B"; // (property) B.kind: "B"
}
function f(value: A | B): number {
switch(value.kind) {
case "A": return 0;
case "B": return 1;
}
}
//// [exhaustiveSwitchWithWideningLiteralTypes.js]
// Repro from #12529
var A = (function () {
function A() {
this.kind = "A"; // (property) A.kind: "A"
}
return A;
}());
var B = (function () {
function B() {
this.kind = "B"; // (property) B.kind: "B"
}
return B;
}());
function f(value) {
switch (value.kind) {
case "A": return 0;
case "B": return 1;
}
}

View File

@ -0,0 +1,33 @@
=== tests/cases/compiler/exhaustiveSwitchWithWideningLiteralTypes.ts ===
// Repro from #12529
class A {
>A : Symbol(A, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 0, 0))
readonly kind = "A"; // (property) A.kind: "A"
>kind : Symbol(A.kind, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 3, 9))
}
class B {
>B : Symbol(B, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 5, 1))
readonly kind = "B"; // (property) B.kind: "B"
>kind : Symbol(B.kind, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 7, 9))
}
function f(value: A | B): number {
>f : Symbol(f, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 9, 1))
>value : Symbol(value, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 11, 11))
>A : Symbol(A, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 0, 0))
>B : Symbol(B, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 5, 1))
switch(value.kind) {
>value.kind : Symbol(kind, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 3, 9), Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 7, 9))
>value : Symbol(value, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 11, 11))
>kind : Symbol(kind, Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 3, 9), Decl(exhaustiveSwitchWithWideningLiteralTypes.ts, 7, 9))
case "A": return 0;
case "B": return 1;
}
}

View File

@ -0,0 +1,40 @@
=== tests/cases/compiler/exhaustiveSwitchWithWideningLiteralTypes.ts ===
// Repro from #12529
class A {
>A : A
readonly kind = "A"; // (property) A.kind: "A"
>kind : "A"
>"A" : "A"
}
class B {
>B : B
readonly kind = "B"; // (property) B.kind: "B"
>kind : "B"
>"B" : "B"
}
function f(value: A | B): number {
>f : (value: A | B) => number
>value : A | B
>A : A
>B : B
switch(value.kind) {
>value.kind : "A" | "B"
>value : A | B
>kind : "A" | "B"
case "A": return 0;
>"A" : "A"
>0 : 0
case "B": return 1;
>"B" : "B"
>1 : 1
}
}

View File

@ -1,8 +1,6 @@
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(12,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(13,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(14,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(16,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(17,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(19,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(20,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(30,16): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
@ -19,7 +17,7 @@ tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInv
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(43,17): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
==== tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts (19 errors) ====
==== tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts (17 errors) ====
enum E { a }
var x: any;
@ -42,11 +40,7 @@ tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInv
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
var ra4 = a4 in x;
var ra5 = null in x;
~~~~
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
var ra6 = undefined in x;
~~~~~~~~~
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
var ra7 = E.a in x;
var ra8 = false in x;
~~~~~

View File

@ -58,6 +58,51 @@ function getValueAsString(value: IntersectionFail): string {
return '' + value.num;
}
return value.str;
}
// Repro from #12535
namespace enums {
export const enum A {
a1,
a2,
a3,
// ... elements omitted for the sake of clarity
a75,
a76,
a77,
}
export const enum B {
b1,
b2,
// ... elements omitted for the sake of clarity
b86,
b87,
}
export const enum C {
c1,
c2,
// ... elements omitted for the sake of clarity
c210,
c211,
}
export type Genre = A | B | C;
}
type Foo = {
genreId: enums.Genre;
};
type Bar = {
genreId: enums.Genre;
};
type FooBar = Foo & Bar;
function foo(so: any) {
const val = so as FooBar;
const isGenre = val.genreId;
return isGenre;
}
//// [intersectionTypeNormalization.js]
@ -77,3 +122,8 @@ function getValueAsString(value) {
}
return value.str;
}
function foo(so) {
var val = so;
var isGenre = val.genreId;
return isGenre;
}

View File

@ -240,3 +240,113 @@ function getValueAsString(value: IntersectionFail): string {
>value : Symbol(value, Decl(intersectionTypeNormalization.ts, 54, 26))
>str : Symbol(str, Decl(intersectionTypeNormalization.ts, 47, 35))
}
// Repro from #12535
namespace enums {
>enums : Symbol(enums, Decl(intersectionTypeNormalization.ts, 59, 1))
export const enum A {
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 63, 17))
a1,
>a1 : Symbol(A.a1, Decl(intersectionTypeNormalization.ts, 64, 25))
a2,
>a2 : Symbol(A.a2, Decl(intersectionTypeNormalization.ts, 65, 11))
a3,
>a3 : Symbol(A.a3, Decl(intersectionTypeNormalization.ts, 66, 11))
// ... elements omitted for the sake of clarity
a75,
>a75 : Symbol(A.a75, Decl(intersectionTypeNormalization.ts, 67, 11))
a76,
>a76 : Symbol(A.a76, Decl(intersectionTypeNormalization.ts, 69, 12))
a77,
>a77 : Symbol(A.a77, Decl(intersectionTypeNormalization.ts, 70, 12))
}
export const enum B {
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 72, 5))
b1,
>b1 : Symbol(B.b1, Decl(intersectionTypeNormalization.ts, 73, 25))
b2,
>b2 : Symbol(B.b2, Decl(intersectionTypeNormalization.ts, 74, 11))
// ... elements omitted for the sake of clarity
b86,
>b86 : Symbol(B.b86, Decl(intersectionTypeNormalization.ts, 75, 11))
b87,
>b87 : Symbol(B.b87, Decl(intersectionTypeNormalization.ts, 77, 12))
}
export const enum C {
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 79, 5))
c1,
>c1 : Symbol(C.c1, Decl(intersectionTypeNormalization.ts, 80, 25))
c2,
>c2 : Symbol(C.c2, Decl(intersectionTypeNormalization.ts, 81, 11))
// ... elements omitted for the sake of clarity
c210,
>c210 : Symbol(C.c210, Decl(intersectionTypeNormalization.ts, 82, 11))
c211,
>c211 : Symbol(C.c211, Decl(intersectionTypeNormalization.ts, 84, 13))
}
export type Genre = A | B | C;
>Genre : Symbol(Genre, Decl(intersectionTypeNormalization.ts, 86, 5))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 63, 17))
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 72, 5))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 79, 5))
}
type Foo = {
>Foo : Symbol(Foo, Decl(intersectionTypeNormalization.ts, 88, 1))
genreId: enums.Genre;
>genreId : Symbol(genreId, Decl(intersectionTypeNormalization.ts, 90, 12))
>enums : Symbol(enums, Decl(intersectionTypeNormalization.ts, 59, 1))
>Genre : Symbol(enums.Genre, Decl(intersectionTypeNormalization.ts, 86, 5))
};
type Bar = {
>Bar : Symbol(Bar, Decl(intersectionTypeNormalization.ts, 92, 2))
genreId: enums.Genre;
>genreId : Symbol(genreId, Decl(intersectionTypeNormalization.ts, 94, 12))
>enums : Symbol(enums, Decl(intersectionTypeNormalization.ts, 59, 1))
>Genre : Symbol(enums.Genre, Decl(intersectionTypeNormalization.ts, 86, 5))
};
type FooBar = Foo & Bar;
>FooBar : Symbol(FooBar, Decl(intersectionTypeNormalization.ts, 96, 2))
>Foo : Symbol(Foo, Decl(intersectionTypeNormalization.ts, 88, 1))
>Bar : Symbol(Bar, Decl(intersectionTypeNormalization.ts, 92, 2))
function foo(so: any) {
>foo : Symbol(foo, Decl(intersectionTypeNormalization.ts, 98, 24))
>so : Symbol(so, Decl(intersectionTypeNormalization.ts, 100, 13))
const val = so as FooBar;
>val : Symbol(val, Decl(intersectionTypeNormalization.ts, 101, 9))
>so : Symbol(so, Decl(intersectionTypeNormalization.ts, 100, 13))
>FooBar : Symbol(FooBar, Decl(intersectionTypeNormalization.ts, 96, 2))
const isGenre = val.genreId;
>isGenre : Symbol(isGenre, Decl(intersectionTypeNormalization.ts, 102, 9))
>val.genreId : Symbol(genreId, Decl(intersectionTypeNormalization.ts, 90, 12), Decl(intersectionTypeNormalization.ts, 94, 12))
>val : Symbol(val, Decl(intersectionTypeNormalization.ts, 101, 9))
>genreId : Symbol(genreId, Decl(intersectionTypeNormalization.ts, 90, 12), Decl(intersectionTypeNormalization.ts, 94, 12))
return isGenre;
>isGenre : Symbol(isGenre, Decl(intersectionTypeNormalization.ts, 102, 9))
}

View File

@ -244,3 +244,114 @@ function getValueAsString(value: IntersectionFail): string {
>value : { kind: "string"; str: string; } & ToString
>str : string
}
// Repro from #12535
namespace enums {
>enums : typeof enums
export const enum A {
>A : A
a1,
>a1 : A.a1
a2,
>a2 : A.a2
a3,
>a3 : A.a3
// ... elements omitted for the sake of clarity
a75,
>a75 : A.a75
a76,
>a76 : A.a76
a77,
>a77 : A.a77
}
export const enum B {
>B : B
b1,
>b1 : B.b1
b2,
>b2 : B.b2
// ... elements omitted for the sake of clarity
b86,
>b86 : B.b86
b87,
>b87 : B.b87
}
export const enum C {
>C : C
c1,
>c1 : C.c1
c2,
>c2 : C.c2
// ... elements omitted for the sake of clarity
c210,
>c210 : C.c210
c211,
>c211 : C.c211
}
export type Genre = A | B | C;
>Genre : Genre
>A : A
>B : B
>C : C
}
type Foo = {
>Foo : Foo
genreId: enums.Genre;
>genreId : enums.Genre
>enums : any
>Genre : enums.Genre
};
type Bar = {
>Bar : Bar
genreId: enums.Genre;
>genreId : enums.Genre
>enums : any
>Genre : enums.Genre
};
type FooBar = Foo & Bar;
>FooBar : FooBar
>Foo : Foo
>Bar : Bar
function foo(so: any) {
>foo : (so: any) => enums.Genre
>so : any
const val = so as FooBar;
>val : FooBar
>so as FooBar : FooBar
>so : any
>FooBar : FooBar
const isGenre = val.genreId;
>isGenre : enums.Genre
>val.genreId : enums.Genre
>val : FooBar
>genreId : enums.Genre
return isGenre;
>isGenre : enums.Genre
}

View File

@ -0,0 +1,10 @@
//// [intersectionTypeWithLeadingOperator.ts]
type A = & string;
type B =
& { foo: string }
& { bar: number };
type C = [& { foo: 1 } & { bar: 2 }, & { foo: 3 } & { bar: 4 }];
//// [intersectionTypeWithLeadingOperator.js]

View File

@ -0,0 +1,20 @@
=== tests/cases/compiler/intersectionTypeWithLeadingOperator.ts ===
type A = & string;
>A : Symbol(A, Decl(intersectionTypeWithLeadingOperator.ts, 0, 0))
type B =
>B : Symbol(B, Decl(intersectionTypeWithLeadingOperator.ts, 0, 18))
& { foo: string }
>foo : Symbol(foo, Decl(intersectionTypeWithLeadingOperator.ts, 2, 5))
& { bar: number };
>bar : Symbol(bar, Decl(intersectionTypeWithLeadingOperator.ts, 3, 5))
type C = [& { foo: 1 } & { bar: 2 }, & { foo: 3 } & { bar: 4 }];
>C : Symbol(C, Decl(intersectionTypeWithLeadingOperator.ts, 3, 20))
>foo : Symbol(foo, Decl(intersectionTypeWithLeadingOperator.ts, 5, 13))
>bar : Symbol(bar, Decl(intersectionTypeWithLeadingOperator.ts, 5, 26))
>foo : Symbol(foo, Decl(intersectionTypeWithLeadingOperator.ts, 5, 40))
>bar : Symbol(bar, Decl(intersectionTypeWithLeadingOperator.ts, 5, 53))

View File

@ -0,0 +1,20 @@
=== tests/cases/compiler/intersectionTypeWithLeadingOperator.ts ===
type A = & string;
>A : string
type B =
>B : B
& { foo: string }
>foo : string
& { bar: number };
>bar : number
type C = [& { foo: 1 } & { bar: 2 }, & { foo: 3 } & { bar: 4 }];
>C : [{ foo: 1; } & { bar: 2; }, { foo: 3; } & { bar: 4; }]
>foo : 1
>bar : 2
>foo : 3
>bar : 4

View File

@ -0,0 +1,222 @@
//// [isomorphicMappedTypeInference.ts]
type Box<T> = {
value: T;
}
type Boxified<T> = {
[P in keyof T]: Box<T[P]>;
}
function box<T>(x: T): Box<T> {
return { value: x };
}
function unbox<T>(x: Box<T>): T {
return x.value;
}
function boxify<T>(obj: T): Boxified<T> {
let result = {} as Boxified<T>;
for (let k in obj) {
result[k] = box(obj[k]);
}
return result;
}
function unboxify<T>(obj: Boxified<T>): T {
let result = {} as T;
for (let k in obj) {
result[k] = unbox(obj[k]);
}
return result;
}
function assignBoxified<T>(obj: Boxified<T>, values: T) {
for (let k in values) {
obj[k].value = values[k];
}
}
function f1() {
let v = {
a: 42,
b: "hello",
c: true
};
let b = boxify(v);
let x: number = b.a.value;
}
function f2() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
let v = unboxify(b);
let x: number = v.a;
}
function f3() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
assignBoxified(b, { c: false });
}
function f4() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
b = boxify(unboxify(b));
b = unboxify(boxify(b));
}
function makeRecord<T, K extends string>(obj: { [P in K]: T }) {
return obj;
}
function f5(s: string) {
let b = makeRecord({
a: box(42),
b: box("hello"),
c: box(true)
});
let v = unboxify(b);
let x: string | number | boolean = v.a;
}
function makeDictionary<T>(obj: { [x: string]: T }) {
return obj;
}
function f6(s: string) {
let b = makeDictionary({
a: box(42),
b: box("hello"),
c: box(true)
});
let v = unboxify(b);
let x: string | number | boolean = v[s];
}
//// [isomorphicMappedTypeInference.js]
function box(x) {
return { value: x };
}
function unbox(x) {
return x.value;
}
function boxify(obj) {
var result = {};
for (var k in obj) {
result[k] = box(obj[k]);
}
return result;
}
function unboxify(obj) {
var result = {};
for (var k in obj) {
result[k] = unbox(obj[k]);
}
return result;
}
function assignBoxified(obj, values) {
for (var k in values) {
obj[k].value = values[k];
}
}
function f1() {
var v = {
a: 42,
b: "hello",
c: true
};
var b = boxify(v);
var x = b.a.value;
}
function f2() {
var b = {
a: box(42),
b: box("hello"),
c: box(true)
};
var v = unboxify(b);
var x = v.a;
}
function f3() {
var b = {
a: box(42),
b: box("hello"),
c: box(true)
};
assignBoxified(b, { c: false });
}
function f4() {
var b = {
a: box(42),
b: box("hello"),
c: box(true)
};
b = boxify(unboxify(b));
b = unboxify(boxify(b));
}
function makeRecord(obj) {
return obj;
}
function f5(s) {
var b = makeRecord({
a: box(42),
b: box("hello"),
c: box(true)
});
var v = unboxify(b);
var x = v.a;
}
function makeDictionary(obj) {
return obj;
}
function f6(s) {
var b = makeDictionary({
a: box(42),
b: box("hello"),
c: box(true)
});
var v = unboxify(b);
var x = v[s];
}
//// [isomorphicMappedTypeInference.d.ts]
declare type Box<T> = {
value: T;
};
declare type Boxified<T> = {
[P in keyof T]: Box<T[P]>;
};
declare function box<T>(x: T): Box<T>;
declare function unbox<T>(x: Box<T>): T;
declare function boxify<T>(obj: T): Boxified<T>;
declare function unboxify<T>(obj: Boxified<T>): T;
declare function assignBoxified<T>(obj: Boxified<T>, values: T): void;
declare function f1(): void;
declare function f2(): void;
declare function f3(): void;
declare function f4(): void;
declare function makeRecord<T, K extends string>(obj: {
[P in K]: T;
}): {
[P in K]: T;
};
declare function f5(s: string): void;
declare function makeDictionary<T>(obj: {
[x: string]: T;
}): {
[x: string]: T;
};
declare function f6(s: string): void;

View File

@ -0,0 +1,334 @@
=== tests/cases/conformance/types/mapped/isomorphicMappedTypeInference.ts ===
type Box<T> = {
>Box : Symbol(Box, Decl(isomorphicMappedTypeInference.ts, 0, 0))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 1, 9))
value: T;
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 1, 9))
}
type Boxified<T> = {
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 3, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 5, 14))
[P in keyof T]: Box<T[P]>;
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 6, 5))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 5, 14))
>Box : Symbol(Box, Decl(isomorphicMappedTypeInference.ts, 0, 0))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 5, 14))
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 6, 5))
}
function box<T>(x: T): Box<T> {
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 9, 13))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 9, 16))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 9, 13))
>Box : Symbol(Box, Decl(isomorphicMappedTypeInference.ts, 0, 0))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 9, 13))
return { value: x };
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 10, 12))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 9, 16))
}
function unbox<T>(x: Box<T>): T {
>unbox : Symbol(unbox, Decl(isomorphicMappedTypeInference.ts, 11, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 13, 15))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 13, 18))
>Box : Symbol(Box, Decl(isomorphicMappedTypeInference.ts, 0, 0))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 13, 15))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 13, 15))
return x.value;
>x.value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 13, 18))
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
}
function boxify<T>(obj: T): Boxified<T> {
>boxify : Symbol(boxify, Decl(isomorphicMappedTypeInference.ts, 15, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 17, 16))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 17, 19))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 17, 16))
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 3, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 17, 16))
let result = {} as Boxified<T>;
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 18, 7))
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 3, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 17, 16))
for (let k in obj) {
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 19, 12))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 17, 19))
result[k] = box(obj[k]);
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 18, 7))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 19, 12))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 17, 19))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 19, 12))
}
return result;
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 18, 7))
}
function unboxify<T>(obj: Boxified<T>): T {
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 25, 18))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 25, 21))
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 3, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 25, 18))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 25, 18))
let result = {} as T;
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 26, 7))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 25, 18))
for (let k in obj) {
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 27, 12))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 25, 21))
result[k] = unbox(obj[k]);
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 26, 7))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 27, 12))
>unbox : Symbol(unbox, Decl(isomorphicMappedTypeInference.ts, 11, 1))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 25, 21))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 27, 12))
}
return result;
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 26, 7))
}
function assignBoxified<T>(obj: Boxified<T>, values: T) {
>assignBoxified : Symbol(assignBoxified, Decl(isomorphicMappedTypeInference.ts, 31, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 33, 24))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 33, 27))
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 3, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 33, 24))
>values : Symbol(values, Decl(isomorphicMappedTypeInference.ts, 33, 44))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 33, 24))
for (let k in values) {
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 34, 12))
>values : Symbol(values, Decl(isomorphicMappedTypeInference.ts, 33, 44))
obj[k].value = values[k];
>obj[k].value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 33, 27))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 34, 12))
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
>values : Symbol(values, Decl(isomorphicMappedTypeInference.ts, 33, 44))
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 34, 12))
}
}
function f1() {
>f1 : Symbol(f1, Decl(isomorphicMappedTypeInference.ts, 37, 1))
let v = {
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 40, 7))
a: 42,
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 40, 13))
b: "hello",
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 41, 14))
c: true
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 42, 19))
};
let b = boxify(v);
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 45, 7))
>boxify : Symbol(boxify, Decl(isomorphicMappedTypeInference.ts, 15, 1))
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 40, 7))
let x: number = b.a.value;
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 46, 7))
>b.a.value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
>b.a : Symbol(a)
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 45, 7))
>a : Symbol(a)
>value : Symbol(value, Decl(isomorphicMappedTypeInference.ts, 1, 15))
}
function f2() {
>f2 : Symbol(f2, Decl(isomorphicMappedTypeInference.ts, 47, 1))
let b = {
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 50, 7))
a: box(42),
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 50, 13))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
b: box("hello"),
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 51, 19))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
c: box(true)
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 52, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
};
let v = unboxify(b);
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 55, 7))
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 50, 7))
let x: number = v.a;
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 56, 7))
>v.a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 50, 13))
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 55, 7))
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 50, 13))
}
function f3() {
>f3 : Symbol(f3, Decl(isomorphicMappedTypeInference.ts, 57, 1))
let b = {
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 60, 7))
a: box(42),
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 60, 13))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
b: box("hello"),
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 61, 19))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
c: box(true)
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 62, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
};
assignBoxified(b, { c: false });
>assignBoxified : Symbol(assignBoxified, Decl(isomorphicMappedTypeInference.ts, 31, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 60, 7))
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 65, 23))
}
function f4() {
>f4 : Symbol(f4, Decl(isomorphicMappedTypeInference.ts, 66, 1))
let b = {
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 69, 7))
a: box(42),
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 69, 13))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
b: box("hello"),
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 70, 19))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
c: box(true)
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 71, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
};
b = boxify(unboxify(b));
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 69, 7))
>boxify : Symbol(boxify, Decl(isomorphicMappedTypeInference.ts, 15, 1))
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 69, 7))
b = unboxify(boxify(b));
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 69, 7))
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>boxify : Symbol(boxify, Decl(isomorphicMappedTypeInference.ts, 15, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 69, 7))
}
function makeRecord<T, K extends string>(obj: { [P in K]: T }) {
>makeRecord : Symbol(makeRecord, Decl(isomorphicMappedTypeInference.ts, 76, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 78, 20))
>K : Symbol(K, Decl(isomorphicMappedTypeInference.ts, 78, 22))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 78, 41))
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 78, 49))
>K : Symbol(K, Decl(isomorphicMappedTypeInference.ts, 78, 22))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 78, 20))
return obj;
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 78, 41))
}
function f5(s: string) {
>f5 : Symbol(f5, Decl(isomorphicMappedTypeInference.ts, 80, 1))
>s : Symbol(s, Decl(isomorphicMappedTypeInference.ts, 82, 12))
let b = makeRecord({
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 83, 7))
>makeRecord : Symbol(makeRecord, Decl(isomorphicMappedTypeInference.ts, 76, 1))
a: box(42),
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 83, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
b: box("hello"),
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 84, 19))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
c: box(true)
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 85, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
});
let v = unboxify(b);
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 88, 7))
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 83, 7))
let x: string | number | boolean = v.a;
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 89, 7))
>v.a : Symbol(a)
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 88, 7))
>a : Symbol(a)
}
function makeDictionary<T>(obj: { [x: string]: T }) {
>makeDictionary : Symbol(makeDictionary, Decl(isomorphicMappedTypeInference.ts, 90, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 92, 24))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 92, 27))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 92, 35))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 92, 24))
return obj;
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 92, 27))
}
function f6(s: string) {
>f6 : Symbol(f6, Decl(isomorphicMappedTypeInference.ts, 94, 1))
>s : Symbol(s, Decl(isomorphicMappedTypeInference.ts, 96, 12))
let b = makeDictionary({
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 97, 7))
>makeDictionary : Symbol(makeDictionary, Decl(isomorphicMappedTypeInference.ts, 90, 1))
a: box(42),
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 97, 28))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
b: box("hello"),
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 98, 19))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
c: box(true)
>c : Symbol(c, Decl(isomorphicMappedTypeInference.ts, 99, 24))
>box : Symbol(box, Decl(isomorphicMappedTypeInference.ts, 7, 1))
});
let v = unboxify(b);
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 102, 7))
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 23, 1))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 97, 7))
let x: string | number | boolean = v[s];
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 103, 7))
>v : Symbol(v, Decl(isomorphicMappedTypeInference.ts, 102, 7))
>s : Symbol(s, Decl(isomorphicMappedTypeInference.ts, 96, 12))
}

View File

@ -0,0 +1,405 @@
=== tests/cases/conformance/types/mapped/isomorphicMappedTypeInference.ts ===
type Box<T> = {
>Box : Box<T>
>T : T
value: T;
>value : T
>T : T
}
type Boxified<T> = {
>Boxified : Boxified<T>
>T : T
[P in keyof T]: Box<T[P]>;
>P : P
>T : T
>Box : Box<T>
>T : T
>P : P
}
function box<T>(x: T): Box<T> {
>box : <T>(x: T) => Box<T>
>T : T
>x : T
>T : T
>Box : Box<T>
>T : T
return { value: x };
>{ value: x } : { value: T; }
>value : T
>x : T
}
function unbox<T>(x: Box<T>): T {
>unbox : <T>(x: Box<T>) => T
>T : T
>x : Box<T>
>Box : Box<T>
>T : T
>T : T
return x.value;
>x.value : T
>x : Box<T>
>value : T
}
function boxify<T>(obj: T): Boxified<T> {
>boxify : <T>(obj: T) => Boxified<T>
>T : T
>obj : T
>T : T
>Boxified : Boxified<T>
>T : T
let result = {} as Boxified<T>;
>result : Boxified<T>
>{} as Boxified<T> : Boxified<T>
>{} : {}
>Boxified : Boxified<T>
>T : T
for (let k in obj) {
>k : keyof T
>obj : T
result[k] = box(obj[k]);
>result[k] = box(obj[k]) : Box<T[keyof T]>
>result[k] : Box<T[keyof T]>
>result : Boxified<T>
>k : keyof T
>box(obj[k]) : Box<T[keyof T]>
>box : <T>(x: T) => Box<T>
>obj[k] : T[keyof T]
>obj : T
>k : keyof T
}
return result;
>result : Boxified<T>
}
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
let result = {} as T;
>result : T
>{} as T : T
>{} : {}
>T : T
for (let k in obj) {
>k : keyof T
>obj : Boxified<T>
result[k] = unbox(obj[k]);
>result[k] = unbox(obj[k]) : T[keyof T]
>result[k] : T[keyof T]
>result : T
>k : keyof T
>unbox(obj[k]) : T[keyof T]
>unbox : <T>(x: Box<T>) => T
>obj[k] : Box<T[keyof T]>
>obj : Boxified<T>
>k : keyof T
}
return result;
>result : T
}
function assignBoxified<T>(obj: Boxified<T>, values: T) {
>assignBoxified : <T>(obj: Boxified<T>, values: T) => void
>T : T
>obj : Boxified<T>
>Boxified : Boxified<T>
>T : T
>values : T
>T : T
for (let k in values) {
>k : keyof T
>values : T
obj[k].value = values[k];
>obj[k].value = values[k] : T[keyof T]
>obj[k].value : T[keyof T]
>obj[k] : Box<T[keyof T]>
>obj : Boxified<T>
>k : keyof T
>value : T[keyof T]
>values[k] : T[keyof T]
>values : T
>k : keyof T
}
}
function f1() {
>f1 : () => void
let v = {
>v : { a: number; b: string; c: boolean; }
>{ a: 42, b: "hello", c: true } : { a: number; b: string; c: boolean; }
a: 42,
>a : number
>42 : 42
b: "hello",
>b : string
>"hello" : "hello"
c: true
>c : boolean
>true : true
};
let b = boxify(v);
>b : Boxified<{ a: number; b: string; c: boolean; }>
>boxify(v) : Boxified<{ a: number; b: string; c: boolean; }>
>boxify : <T>(obj: T) => Boxified<T>
>v : { a: number; b: string; c: boolean; }
let x: number = b.a.value;
>x : number
>b.a.value : number
>b.a : Box<number>
>b : Boxified<{ a: number; b: string; c: boolean; }>
>a : Box<number>
>value : number
}
function f2() {
>f2 : () => void
let b = {
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>{ a: box(42), b: box("hello"), c: box(true) } : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
a: box(42),
>a : Box<number>
>box(42) : Box<number>
>box : <T>(x: T) => Box<T>
>42 : 42
b: box("hello"),
>b : Box<string>
>box("hello") : Box<string>
>box : <T>(x: T) => Box<T>
>"hello" : "hello"
c: box(true)
>c : Box<boolean>
>box(true) : Box<boolean>
>box : <T>(x: T) => Box<T>
>true : true
};
let v = unboxify(b);
>v : { a: number; b: string; c: boolean; }
>unboxify(b) : { a: number; b: string; c: boolean; }
>unboxify : <T>(obj: Boxified<T>) => T
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
let x: number = v.a;
>x : number
>v.a : number
>v : { a: number; b: string; c: boolean; }
>a : number
}
function f3() {
>f3 : () => void
let b = {
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>{ a: box(42), b: box("hello"), c: box(true) } : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
a: box(42),
>a : Box<number>
>box(42) : Box<number>
>box : <T>(x: T) => Box<T>
>42 : 42
b: box("hello"),
>b : Box<string>
>box("hello") : Box<string>
>box : <T>(x: T) => Box<T>
>"hello" : "hello"
c: box(true)
>c : Box<boolean>
>box(true) : Box<boolean>
>box : <T>(x: T) => Box<T>
>true : true
};
assignBoxified(b, { c: false });
>assignBoxified(b, { c: false }) : void
>assignBoxified : <T>(obj: Boxified<T>, values: T) => void
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>{ c: false } : { c: false; }
>c : boolean
>false : false
}
function f4() {
>f4 : () => void
let b = {
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>{ a: box(42), b: box("hello"), c: box(true) } : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
a: box(42),
>a : Box<number>
>box(42) : Box<number>
>box : <T>(x: T) => Box<T>
>42 : 42
b: box("hello"),
>b : Box<string>
>box("hello") : Box<string>
>box : <T>(x: T) => Box<T>
>"hello" : "hello"
c: box(true)
>c : Box<boolean>
>box(true) : Box<boolean>
>box : <T>(x: T) => Box<T>
>true : true
};
b = boxify(unboxify(b));
>b = boxify(unboxify(b)) : Boxified<{ a: number; b: string; c: boolean; }>
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>boxify(unboxify(b)) : Boxified<{ a: number; b: string; c: boolean; }>
>boxify : <T>(obj: T) => Boxified<T>
>unboxify(b) : { a: number; b: string; c: boolean; }
>unboxify : <T>(obj: Boxified<T>) => T
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
b = unboxify(boxify(b));
>b = unboxify(boxify(b)) : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>unboxify(boxify(b)) : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
>unboxify : <T>(obj: Boxified<T>) => T
>boxify(b) : Boxified<{ a: Box<number>; b: Box<string>; c: Box<boolean>; }>
>boxify : <T>(obj: T) => Boxified<T>
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
}
function makeRecord<T, K extends string>(obj: { [P in K]: T }) {
>makeRecord : <T, K extends string>(obj: { [P in K]: T; }) => { [P in K]: T; }
>T : T
>K : K
>obj : { [P in K]: T; }
>P : P
>K : K
>T : T
return obj;
>obj : { [P in K]: T; }
}
function f5(s: string) {
>f5 : (s: string) => void
>s : string
let b = makeRecord({
>b : { a: Box<number> | Box<string> | Box<boolean>; b: Box<number> | Box<string> | Box<boolean>; c: Box<number> | Box<string> | Box<boolean>; }
>makeRecord({ a: box(42), b: box("hello"), c: box(true) }) : { a: Box<number> | Box<string> | Box<boolean>; b: Box<number> | Box<string> | Box<boolean>; c: Box<number> | Box<string> | Box<boolean>; }
>makeRecord : <T, K extends string>(obj: { [P in K]: T; }) => { [P in K]: T; }
>{ a: box(42), b: box("hello"), c: box(true) } : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
a: box(42),
>a : Box<number>
>box(42) : Box<number>
>box : <T>(x: T) => Box<T>
>42 : 42
b: box("hello"),
>b : Box<string>
>box("hello") : Box<string>
>box : <T>(x: T) => Box<T>
>"hello" : "hello"
c: box(true)
>c : Box<boolean>
>box(true) : Box<boolean>
>box : <T>(x: T) => Box<T>
>true : true
});
let v = unboxify(b);
>v : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
>unboxify(b) : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
>unboxify : <T>(obj: Boxified<T>) => T
>b : { a: Box<number> | Box<string> | Box<boolean>; b: Box<number> | Box<string> | Box<boolean>; c: Box<number> | Box<string> | Box<boolean>; }
let x: string | number | boolean = v.a;
>x : string | number | boolean
>v.a : string | number | boolean
>v : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
>a : string | number | boolean
}
function makeDictionary<T>(obj: { [x: string]: T }) {
>makeDictionary : <T>(obj: { [x: string]: T; }) => { [x: string]: T; }
>T : T
>obj : { [x: string]: T; }
>x : string
>T : T
return obj;
>obj : { [x: string]: T; }
}
function f6(s: string) {
>f6 : (s: string) => void
>s : string
let b = makeDictionary({
>b : { [x: string]: Box<number> | Box<string> | Box<boolean>; }
>makeDictionary({ a: box(42), b: box("hello"), c: box(true) }) : { [x: string]: Box<number> | Box<string> | Box<boolean>; }
>makeDictionary : <T>(obj: { [x: string]: T; }) => { [x: string]: T; }
>{ a: box(42), b: box("hello"), c: box(true) } : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
a: box(42),
>a : Box<number>
>box(42) : Box<number>
>box : <T>(x: T) => Box<T>
>42 : 42
b: box("hello"),
>b : Box<string>
>box("hello") : Box<string>
>box : <T>(x: T) => Box<T>
>"hello" : "hello"
c: box(true)
>c : Box<boolean>
>box(true) : Box<boolean>
>box : <T>(x: T) => Box<T>
>true : true
});
let v = unboxify(b);
>v : { [x: string]: string | number | boolean; }
>unboxify(b) : { [x: string]: string | number | boolean; }
>unboxify : <T>(obj: Boxified<T>) => T
>b : { [x: string]: Box<number> | Box<string> | Box<boolean>; }
let x: string | number | boolean = v[s];
>x : string | number | boolean
>v[s] : string | number | boolean
>v : { [x: string]: string | number | boolean; }
>s : string
}

View File

@ -0,0 +1,81 @@
//// [keyofAndForIn.ts]
// Repro from #12513
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
const b = k in obj;
let k1: K;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
const b = k in obj;
let k1: keyof T;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
const b = k in obj;
let k1: K;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}
//// [keyofAndForIn.js]
// Repro from #12513
function f1(obj, k) {
var b = k in obj;
var k1;
for (k1 in obj) {
var x1 = obj[k1];
}
for (var k2 in obj) {
var x2 = obj[k2];
}
}
function f2(obj, k) {
var b = k in obj;
var k1;
for (k1 in obj) {
var x1 = obj[k1];
}
for (var k2 in obj) {
var x2 = obj[k2];
}
}
function f3(obj, k) {
var b = k in obj;
var k1;
for (k1 in obj) {
var x1 = obj[k1];
}
for (var k2 in obj) {
var x2 = obj[k2];
}
}
//// [keyofAndForIn.d.ts]
declare function f1<K extends string, T>(obj: {
[P in K]: T;
}, k: K): void;
declare function f2<T>(obj: {
[P in keyof T]: T[P];
}, k: keyof T): void;
declare function f3<T, K extends keyof T>(obj: {
[P in K]: T[P];
}, k: K): void;

View File

@ -0,0 +1,125 @@
=== tests/cases/conformance/types/keyof/keyofAndForIn.ts ===
// Repro from #12513
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
>f1 : Symbol(f1, Decl(keyofAndForIn.ts, 0, 0))
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
>T : Symbol(T, Decl(keyofAndForIn.ts, 3, 29))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
>P : Symbol(P, Decl(keyofAndForIn.ts, 3, 41))
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
>T : Symbol(T, Decl(keyofAndForIn.ts, 3, 29))
>k : Symbol(k, Decl(keyofAndForIn.ts, 3, 54))
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
const b = k in obj;
>b : Symbol(b, Decl(keyofAndForIn.ts, 4, 9))
>k : Symbol(k, Decl(keyofAndForIn.ts, 3, 54))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
let k1: K;
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
for (k1 in obj) {
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
let x1 = obj[k1];
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 7, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
}
for (let k2 in obj) {
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 9, 12))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
let x2 = obj[k2];
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 10, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 9, 12))
}
}
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
>f2 : Symbol(f2, Decl(keyofAndForIn.ts, 12, 1))
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
>P : Symbol(P, Decl(keyofAndForIn.ts, 14, 23))
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
>P : Symbol(P, Decl(keyofAndForIn.ts, 14, 23))
>k : Symbol(k, Decl(keyofAndForIn.ts, 14, 45))
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
const b = k in obj;
>b : Symbol(b, Decl(keyofAndForIn.ts, 15, 9))
>k : Symbol(k, Decl(keyofAndForIn.ts, 14, 45))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
let k1: keyof T;
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
for (k1 in obj) {
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
let x1 = obj[k1];
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 18, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
}
for (let k2 in obj) {
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 20, 12))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
let x2 = obj[k2];
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 21, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 20, 12))
}
}
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
>f3 : Symbol(f3, Decl(keyofAndForIn.ts, 23, 1))
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
>P : Symbol(P, Decl(keyofAndForIn.ts, 25, 42))
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
>P : Symbol(P, Decl(keyofAndForIn.ts, 25, 42))
>k : Symbol(k, Decl(keyofAndForIn.ts, 25, 58))
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
const b = k in obj;
>b : Symbol(b, Decl(keyofAndForIn.ts, 26, 9))
>k : Symbol(k, Decl(keyofAndForIn.ts, 25, 58))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
let k1: K;
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
for (k1 in obj) {
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
let x1 = obj[k1];
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 29, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
}
for (let k2 in obj) {
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 31, 12))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
let x2 = obj[k2];
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 32, 11))
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 31, 12))
}
}

View File

@ -0,0 +1,134 @@
=== tests/cases/conformance/types/keyof/keyofAndForIn.ts ===
// Repro from #12513
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
>f1 : <K extends string, T>(obj: { [P in K]: T; }, k: K) => void
>K : K
>T : T
>obj : { [P in K]: T; }
>P : P
>K : K
>T : T
>k : K
>K : K
const b = k in obj;
>b : boolean
>k in obj : boolean
>k : K
>obj : { [P in K]: T; }
let k1: K;
>k1 : K
>K : K
for (k1 in obj) {
>k1 : K
>obj : { [P in K]: T; }
let x1 = obj[k1];
>x1 : T
>obj[k1] : T
>obj : { [P in K]: T; }
>k1 : K
}
for (let k2 in obj) {
>k2 : K
>obj : { [P in K]: T; }
let x2 = obj[k2];
>x2 : T
>obj[k2] : T
>obj : { [P in K]: T; }
>k2 : K
}
}
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
>f2 : <T>(obj: { [P in keyof T]: T[P]; }, k: keyof T) => void
>T : T
>obj : { [P in keyof T]: T[P]; }
>P : P
>T : T
>T : T
>P : P
>k : keyof T
>T : T
const b = k in obj;
>b : boolean
>k in obj : boolean
>k : keyof T
>obj : { [P in keyof T]: T[P]; }
let k1: keyof T;
>k1 : keyof T
>T : T
for (k1 in obj) {
>k1 : keyof T
>obj : { [P in keyof T]: T[P]; }
let x1 = obj[k1];
>x1 : T[keyof T]
>obj[k1] : T[keyof T]
>obj : { [P in keyof T]: T[P]; }
>k1 : keyof T
}
for (let k2 in obj) {
>k2 : keyof T
>obj : { [P in keyof T]: T[P]; }
let x2 = obj[k2];
>x2 : T[keyof T]
>obj[k2] : T[keyof T]
>obj : { [P in keyof T]: T[P]; }
>k2 : keyof T
}
}
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
>f3 : <T, K extends keyof T>(obj: { [P in K]: T[P]; }, k: K) => void
>T : T
>K : K
>T : T
>obj : { [P in K]: T[P]; }
>P : P
>K : K
>T : T
>P : P
>k : K
>K : K
const b = k in obj;
>b : boolean
>k in obj : boolean
>k : K
>obj : { [P in K]: T[P]; }
let k1: K;
>k1 : K
>K : K
for (k1 in obj) {
>k1 : K
>obj : { [P in K]: T[P]; }
let x1 = obj[k1];
>x1 : T[K]
>obj[k1] : T[K]
>obj : { [P in K]: T[P]; }
>k1 : K
}
for (let k2 in obj) {
>k2 : K
>obj : { [P in K]: T[P]; }
let x2 = obj[k2];
>x2 : T[K]
>obj[k2] : T[K]
>obj : { [P in K]: T[P]; }
>k2 : K
}
}

View File

@ -21,11 +21,12 @@ class Options {
}
type Dictionary<T> = { [x: string]: T };
type NumericallyIndexed<T> = { [x: number]: T };
const enum E { A, B, C }
type K00 = keyof any; // string | number
type K01 = keyof string; // number | "toString" | "charAt" | ...
type K00 = keyof any; // string
type K01 = keyof string; // "toString" | "charAt" | ...
type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ...
type K03 = keyof boolean; // "valueOf"
type K04 = keyof void; // never
@ -34,19 +35,20 @@ type K06 = keyof null; // never
type K07 = keyof never; // never
type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
type K11 = keyof Shape[]; // number | "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string | number
type K11 = keyof Shape[]; // "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string
type K13 = keyof {}; // never
type K14 = keyof Object; // "constructor" | "toString" | ...
type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ...
type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ...
type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ...
type K17 = keyof (Shape | Item); // "name"
type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price"
type K19 = keyof NumericallyIndexed<Shape> // never
type KeyOf<T> = keyof T;
type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
type K21 = KeyOf<Dictionary<Shape>>; // string | number
type K21 = KeyOf<Dictionary<Shape>>; // string
type NAME = "name";
type WIDTH_OR_HEIGHT = "width" | "height";
@ -247,7 +249,8 @@ class OtherPerson {
getParts() {
return getProperty(this, "parts")
}
}
}
//// [keyofAndIndexedAccess.js]
var __extends = (this && this.__extends) || function (d, b) {
@ -449,6 +452,9 @@ declare class Options {
declare type Dictionary<T> = {
[x: string]: T;
};
declare type NumericallyIndexed<T> = {
[x: number]: T;
};
declare const enum E {
A = 0,
B = 1,
@ -471,6 +477,7 @@ declare type K15 = keyof E;
declare type K16 = keyof [string, number];
declare type K17 = keyof (Shape | Item);
declare type K18 = keyof (Shape & Item);
declare type K19 = keyof NumericallyIndexed<Shape>;
declare type KeyOf<T> = keyof T;
declare type K20 = KeyOf<Shape>;
declare type K21 = KeyOf<Dictionary<Shape>>;

File diff suppressed because it is too large Load Diff

View File

@ -47,16 +47,22 @@ type Dictionary<T> = { [x: string]: T };
>x : string
>T : T
type NumericallyIndexed<T> = { [x: number]: T };
>NumericallyIndexed : NumericallyIndexed<T>
>T : T
>x : number
>T : T
const enum E { A, B, C }
>E : E
>A : E.A
>B : E.B
>C : E.C
type K00 = keyof any; // string | number
type K00 = keyof any; // string
>K00 : string
type K01 = keyof string; // number | "toString" | "charAt" | ...
type K01 = keyof string; // "toString" | "charAt" | ...
>K01 : "length" | "toString" | "concat" | "slice" | "indexOf" | "lastIndexOf" | "charAt" | "charCodeAt" | "localeCompare" | "match" | "replace" | "search" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" | "valueOf"
type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ...
@ -82,11 +88,11 @@ type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
>K10 : "name" | "width" | "height" | "visible"
>Shape : Shape
type K11 = keyof Shape[]; // number | "length" | "toString" | ...
type K11 = keyof Shape[]; // "length" | "toString" | ...
>K11 : "length" | "toString" | "toLocaleString" | "push" | "pop" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"
>Shape : Shape
type K12 = keyof Dictionary<Shape>; // string | number
type K12 = keyof Dictionary<Shape>; // string
>K12 : string
>Dictionary : Dictionary<T>
>Shape : Shape
@ -102,7 +108,7 @@ type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ...
>K15 : "toString" | "toLocaleString" | "valueOf" | "toFixed" | "toExponential" | "toPrecision"
>E : E
type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ...
type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ...
>K16 : "0" | "1" | "length" | "toString" | "toLocaleString" | "push" | "pop" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight"
type K17 = keyof (Shape | Item); // "name"
@ -115,6 +121,11 @@ type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "
>Shape : Shape
>Item : Item
type K19 = keyof NumericallyIndexed<Shape> // never
>K19 : never
>NumericallyIndexed : NumericallyIndexed<T>
>Shape : Shape
type KeyOf<T> = keyof T;
>KeyOf : keyof T
>T : T
@ -125,7 +136,7 @@ type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
>KeyOf : keyof T
>Shape : Shape
type K21 = KeyOf<Dictionary<Shape>>; // string | number
type K21 = KeyOf<Dictionary<Shape>>; // string
>K21 : string
>KeyOf : keyof T
>Dictionary : Dictionary<T>
@ -970,3 +981,4 @@ class OtherPerson {
>"parts" : "parts"
}
}

View File

@ -0,0 +1,12 @@
//// [mappedTypeInferenceCircularity.ts]
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
type Block<P> = <T>(func: HTML) => {};
declare var h: HTML;
h.div(h);
//// [mappedTypeInferenceCircularity.js]
// Repro from #12511
h.div(h);

View File

@ -0,0 +1,26 @@
=== tests/cases/compiler/mappedTypeInferenceCircularity.ts ===
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
>K : Symbol(K, Decl(mappedTypeInferenceCircularity.ts, 2, 15))
>Block : Symbol(Block, Decl(mappedTypeInferenceCircularity.ts, 2, 42))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
type Block<P> = <T>(func: HTML) => {};
>Block : Symbol(Block, Decl(mappedTypeInferenceCircularity.ts, 2, 42))
>P : Symbol(P, Decl(mappedTypeInferenceCircularity.ts, 3, 11))
>T : Symbol(T, Decl(mappedTypeInferenceCircularity.ts, 3, 17))
>func : Symbol(func, Decl(mappedTypeInferenceCircularity.ts, 3, 20))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
declare var h: HTML;
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
h.div(h);
>h.div : Symbol(div)
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))
>div : Symbol(div)
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))

View File

@ -0,0 +1,27 @@
=== tests/cases/compiler/mappedTypeInferenceCircularity.ts ===
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
>HTML : HTML
>K : K
>Block : Block<P>
>HTML : HTML
type Block<P> = <T>(func: HTML) => {};
>Block : Block<P>
>P : P
>T : T
>func : HTML
>HTML : HTML
declare var h: HTML;
>h : HTML
>HTML : HTML
h.div(h);
>h.div(h) : {}
>h.div : Block<HTML>
>h : HTML
>div : Block<HTML>
>h : HTML

View File

@ -0,0 +1,10 @@
//// [unionTypeWithLeadingOperator.ts]
type A = | string;
type B =
| { type: "INCREMENT" }
| { type: "DECREMENT" };
type C = [| 0 | 1, | "foo" | "bar"];
//// [unionTypeWithLeadingOperator.js]

View File

@ -0,0 +1,16 @@
=== tests/cases/compiler/unionTypeWithLeadingOperator.ts ===
type A = | string;
>A : Symbol(A, Decl(unionTypeWithLeadingOperator.ts, 0, 0))
type B =
>B : Symbol(B, Decl(unionTypeWithLeadingOperator.ts, 0, 18))
| { type: "INCREMENT" }
>type : Symbol(type, Decl(unionTypeWithLeadingOperator.ts, 2, 5))
| { type: "DECREMENT" };
>type : Symbol(type, Decl(unionTypeWithLeadingOperator.ts, 3, 5))
type C = [| 0 | 1, | "foo" | "bar"];
>C : Symbol(C, Decl(unionTypeWithLeadingOperator.ts, 3, 26))

View File

@ -0,0 +1,16 @@
=== tests/cases/compiler/unionTypeWithLeadingOperator.ts ===
type A = | string;
>A : string
type B =
>B : B
| { type: "INCREMENT" }
>type : "INCREMENT"
| { type: "DECREMENT" };
>type : "DECREMENT"
type C = [| 0 | 1, | "foo" | "bar"];
>C : [0 | 1, "foo" | "bar"]

View File

@ -1,5 +1,4 @@
tests/cases/compiler/widenedTypes.ts(2,1): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
tests/cases/compiler/widenedTypes.ts(5,1): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
tests/cases/compiler/widenedTypes.ts(6,7): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
tests/cases/compiler/widenedTypes.ts(8,15): error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.
tests/cases/compiler/widenedTypes.ts(10,14): error TS2695: Left side of comma operator is unused and has no side effects.
@ -12,7 +11,7 @@ tests/cases/compiler/widenedTypes.ts(24,5): error TS2322: Type '{ x: number; y:
Type 'number' is not assignable to type 'string'.
==== tests/cases/compiler/widenedTypes.ts (9 errors) ====
==== tests/cases/compiler/widenedTypes.ts (8 errors) ====
null instanceof (() => { });
~~~~
@ -20,8 +19,6 @@ tests/cases/compiler/widenedTypes.ts(24,5): error TS2322: Type '{ x: number; y:
({}) instanceof null; // Ok because null is a subtype of function
null in {};
~~~~
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
"" in null;
~~~~
!!! error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter

View File

@ -0,0 +1,18 @@
// @strictNullChecks: true
// Repro from #12529
class A {
readonly kind = "A"; // (property) A.kind: "A"
}
class B {
readonly kind = "B"; // (property) B.kind: "B"
}
function f(value: A | B): number {
switch(value.kind) {
case "A": return 0;
case "B": return 1;
}
}

View File

@ -57,4 +57,49 @@ function getValueAsString(value: IntersectionFail): string {
return '' + value.num;
}
return value.str;
}
// Repro from #12535
namespace enums {
export const enum A {
a1,
a2,
a3,
// ... elements omitted for the sake of clarity
a75,
a76,
a77,
}
export const enum B {
b1,
b2,
// ... elements omitted for the sake of clarity
b86,
b87,
}
export const enum C {
c1,
c2,
// ... elements omitted for the sake of clarity
c210,
c211,
}
export type Genre = A | B | C;
}
type Foo = {
genreId: enums.Genre;
};
type Bar = {
genreId: enums.Genre;
};
type FooBar = Foo & Bar;
function foo(so: any) {
const val = so as FooBar;
const isGenre = val.genreId;
return isGenre;
}

View File

@ -0,0 +1,6 @@
type A = & string;
type B =
& { foo: string }
& { bar: number };
type C = [& { foo: 1 } & { bar: 2 }, & { foo: 3 } & { bar: 4 }];

View File

@ -0,0 +1,7 @@
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
type Block<P> = <T>(func: HTML) => {};
declare var h: HTML;
h.div(h);

View File

@ -0,0 +1,6 @@
type A = | string;
type B =
| { type: "INCREMENT" }
| { type: "DECREMENT" };
type C = [| 0 | 1, | "foo" | "bar"];

View File

@ -0,0 +1,36 @@
// @declaration: true
// Repro from #12513
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
const b = k in obj;
let k1: K;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
const b = k in obj;
let k1: keyof T;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
const b = k in obj;
let k1: K;
for (k1 in obj) {
let x1 = obj[k1];
}
for (let k2 in obj) {
let x2 = obj[k2];
}
}

View File

@ -21,11 +21,12 @@ class Options {
}
type Dictionary<T> = { [x: string]: T };
type NumericallyIndexed<T> = { [x: number]: T };
const enum E { A, B, C }
type K00 = keyof any; // string | number
type K01 = keyof string; // number | "toString" | "charAt" | ...
type K00 = keyof any; // string
type K01 = keyof string; // "toString" | "charAt" | ...
type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ...
type K03 = keyof boolean; // "valueOf"
type K04 = keyof void; // never
@ -34,19 +35,20 @@ type K06 = keyof null; // never
type K07 = keyof never; // never
type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
type K11 = keyof Shape[]; // number | "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string | number
type K11 = keyof Shape[]; // "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>; // string
type K13 = keyof {}; // never
type K14 = keyof Object; // "constructor" | "toString" | ...
type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ...
type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ...
type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ...
type K17 = keyof (Shape | Item); // "name"
type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price"
type K19 = keyof NumericallyIndexed<Shape> // never
type KeyOf<T> = keyof T;
type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
type K21 = KeyOf<Dictionary<Shape>>; // string | number
type K21 = KeyOf<Dictionary<Shape>>; // string
type NAME = "name";
type WIDTH_OR_HEIGHT = "width" | "height";
@ -247,4 +249,4 @@ class OtherPerson {
getParts() {
return getProperty(this, "parts")
}
}
}

View File

@ -0,0 +1,107 @@
// @noimplicitany: true
// @declaration: true
type Box<T> = {
value: T;
}
type Boxified<T> = {
[P in keyof T]: Box<T[P]>;
}
function box<T>(x: T): Box<T> {
return { value: x };
}
function unbox<T>(x: Box<T>): T {
return x.value;
}
function boxify<T>(obj: T): Boxified<T> {
let result = {} as Boxified<T>;
for (let k in obj) {
result[k] = box(obj[k]);
}
return result;
}
function unboxify<T>(obj: Boxified<T>): T {
let result = {} as T;
for (let k in obj) {
result[k] = unbox(obj[k]);
}
return result;
}
function assignBoxified<T>(obj: Boxified<T>, values: T) {
for (let k in values) {
obj[k].value = values[k];
}
}
function f1() {
let v = {
a: 42,
b: "hello",
c: true
};
let b = boxify(v);
let x: number = b.a.value;
}
function f2() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
let v = unboxify(b);
let x: number = v.a;
}
function f3() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
assignBoxified(b, { c: false });
}
function f4() {
let b = {
a: box(42),
b: box("hello"),
c: box(true)
};
b = boxify(unboxify(b));
b = unboxify(boxify(b));
}
function makeRecord<T, K extends string>(obj: { [P in K]: T }) {
return obj;
}
function f5(s: string) {
let b = makeRecord({
a: box(42),
b: box("hello"),
c: box(true)
});
let v = unboxify(b);
let x: string | number | boolean = v.a;
}
function makeDictionary<T>(obj: { [x: string]: T }) {
return obj;
}
function f6(s: string) {
let b = makeDictionary({
a: box(42),
b: box("hello"),
c: box(true)
});
let v = unboxify(b);
let x: string | number | boolean = v[s];
}