Merge branch 'master' into release-2.1

This commit is contained in:
Mohamed Hegazy 2016-12-05 10:19:37 -08:00
commit ae3b6e7841
19 changed files with 2052 additions and 138 deletions

View File

@ -4513,17 +4513,17 @@ namespace ts {
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,
// and T as the template type. If K is of the form 'keyof S', the mapped type and S are
// isomorphic and we copy property modifiers from corresponding properties in S.
// homomorphic and we copy property modifiers from corresponding properties in S.
const typeParameter = getTypeParameterFromMappedType(type);
const constraintType = getConstraintTypeFromMappedType(type);
const isomorphicType = getIsomorphicTypeFromMappedType(type);
const homomorphicType = getHomomorphicTypeFromMappedType(type);
const templateType = getTemplateTypeFromMappedType(type);
const templateReadonly = !!type.declaration.readonlyToken;
const templateOptional = !!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 keyType = constraintType.flags & TypeFlags.TypeVariable ? 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
@ -4536,11 +4536,11 @@ namespace ts {
// Otherwise, for type string create a string index signature.
if (t.flags & TypeFlags.StringLiteral) {
const propName = (<LiteralType>t).text;
const isomorphicProp = isomorphicType && getPropertyOfType(isomorphicType, propName);
const isOptional = templateOptional || !!(isomorphicProp && isomorphicProp.flags & SymbolFlags.Optional);
const homomorphicProp = homomorphicType && getPropertyOfType(homomorphicType, propName);
const isOptional = templateOptional || !!(homomorphicProp && homomorphicProp.flags & SymbolFlags.Optional);
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
prop.type = propType;
prop.isReadonly = templateReadonly || isomorphicProp && isReadonlySymbol(isomorphicProp);
prop.isReadonly = templateReadonly || homomorphicProp && isReadonlySymbol(homomorphicProp);
members[propName] = prop;
}
else if (t.flags & TypeFlags.String) {
@ -4567,7 +4567,7 @@ namespace ts {
unknownType);
}
function getIsomorphicTypeFromMappedType(type: MappedType) {
function getHomomorphicTypeFromMappedType(type: MappedType) {
const constraint = getConstraintDeclaration(getTypeParameterFromMappedType(type));
return constraint.kind === SyntaxKind.TypeOperator ? instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraint).type), type.mapper || identityMapper) : undefined;
}
@ -4579,7 +4579,7 @@ namespace ts {
function isGenericMappedType(type: Type) {
if (getObjectFlags(type) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
return !!(constraintType.flags & (TypeFlags.TypeParameter | TypeFlags.Index));
return maybeTypeOfKind(constraintType, TypeFlags.TypeVariable | TypeFlags.Index);
}
return false;
}
@ -5912,7 +5912,7 @@ namespace ts {
return links.resolvedType;
}
function getIndexTypeForTypeParameter(type: TypeParameter) {
function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType) {
if (!type.resolvedIndexType) {
type.resolvedIndexType = <IndexType>createType(TypeFlags.Index);
type.resolvedIndexType.type = type;
@ -5931,7 +5931,7 @@ namespace ts {
}
function getIndexType(type: Type): Type {
return type.flags & TypeFlags.TypeParameter ? getIndexTypeForTypeParameter(<TypeParameter>type) :
return maybeTypeOfKind(type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType(<TypeVariable | UnionOrIntersectionType>type) :
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
getLiteralTypeFromPropertyNames(type);
@ -6032,13 +6032,14 @@ namespace ts {
}
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
if (indexType.flags & TypeFlags.TypeParameter ||
objectType.flags & TypeFlags.TypeParameter && indexType.flags & TypeFlags.Index ||
isGenericMappedType(objectType)) {
// If either the object type or the index type are type parameters, or if the object type is a mapped
// type with a generic constraint, we are performing a higher-order index access where we cannot
// 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 (maybeTypeOfKind(indexType, TypeFlags.TypeVariable | TypeFlags.Index) || isGenericMappedType(objectType)) {
if (objectType.flags & TypeFlags.Any) {
return objectType;
}
// If the index type is generic or if the object type is a mapped type with a generic constraint,
// we are performing a higher-order index access where we cannot 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) {
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
@ -6531,19 +6532,19 @@ namespace ts {
}
function instantiateMappedType(type: MappedType, mapper: TypeMapper): Type {
// Check if we have an isomorphic mapped type, i.e. a type of the form { [P in keyof T]: X } for some
// type parameter T. If so, the mapped type is distributive over a union type and when T is instantiated
// Check if we have a homomorphic mapped type, i.e. a type of the form { [P in keyof T]: X } for some
// type variable T. If so, the mapped type is distributive over a union type and when T is instantiated
// to a union type A | B, we produce { [P in keyof A]: X } | { [P in keyof B]: X }. Furthermore, for
// isomorphic mapped types we leave primitive types alone. For example, when T is instantiated to a
// homomorphic mapped types we leave primitive types alone. For example, when T is instantiated to a
// union type A | undefined, we produce { [P in keyof A]: X } | undefined.
const constraintType = getConstraintTypeFromMappedType(type);
if (constraintType.flags & TypeFlags.Index) {
const typeParameter = (<IndexType>constraintType).type;
const mappedTypeParameter = mapper(typeParameter);
if (typeParameter !== mappedTypeParameter) {
return mapType(mappedTypeParameter, t => {
const typeVariable = (<IndexType>constraintType).type;
const mappedTypeVariable = instantiateType(typeVariable, mapper);
if (typeVariable !== mappedTypeVariable) {
return mapType(mappedTypeVariable, t => {
if (isMappableType(t)) {
const replacementMapper = createUnaryTypeMapper(typeParameter, t);
const replacementMapper = createUnaryTypeMapper(typeVariable, t);
const combinedMapper = mapper.mappedTypes && mapper.mappedTypes.length === 1 ? replacementMapper : combineTypeMappers(replacementMapper, mapper);
combinedMapper.mappedTypes = mapper.mappedTypes;
return instantiateMappedObjectType(type, combinedMapper);
@ -7274,10 +7275,12 @@ namespace ts {
}
// 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);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
return result;
if ((<IndexType>target).type.flags & TypeFlags.TypeParameter) {
const constraint = getConstraintOfTypeParameter(<TypeParameter>(<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
return result;
}
}
}
}
@ -8458,69 +8461,68 @@ namespace ts {
// Return true if the given type could possibly reference a type parameter for which
// 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 {
function couldContainTypeVariables(type: Type): boolean {
const objectFlags = getObjectFlags(type);
return !!(type.flags & (TypeFlags.TypeParameter | TypeFlags.IndexedAccess) ||
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
return !!(type.flags & TypeFlags.TypeVariable ||
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeVariables) ||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
objectFlags & ObjectFlags.Mapped ||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeVariables(<UnionOrIntersectionType>type));
}
function couldUnionOrIntersectionContainTypeParameters(type: UnionOrIntersectionType): boolean {
if (type.couldContainTypeParameters === undefined) {
type.couldContainTypeParameters = forEach(type.types, couldContainTypeParameters);
function couldUnionOrIntersectionContainTypeVariables(type: UnionOrIntersectionType): boolean {
if (type.couldContainTypeVariables === undefined) {
type.couldContainTypeVariables = forEach(type.types, couldContainTypeVariables);
}
return type.couldContainTypeParameters;
return type.couldContainTypeVariables;
}
function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
}
// Infer a suitable input type for an isomorphic mapped type { [P in keyof T]: X }. We construct
// Infer a suitable input type for a homomorphic 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;
// property is computed by inferring from the source property type to X for the type
// variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for).
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType): Type {
const properties = getPropertiesOfType(source);
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
if (properties.length === 0 && !indexInfo) {
return undefined;
}
const typeParameter = getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
const typeParameterArray = [typeParameter];
const typeVariable = <TypeVariable>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
const typeVariableArray = [typeVariable];
const typeInferences = createTypeInferencesObject();
const typeInferencesArray = [typeInferences];
const templateType = getTemplateTypeFromMappedType(target);
const readonlyMask = target.declaration.readonlyToken ? false : true;
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
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 & optionalMask, prop.name);
inferredProp.declarations = prop.declarations;
inferredProp.type = inferredPropType;
inferredProp.isReadonly = readonlyMask && isReadonlySymbol(prop);
members[prop.name] = inferredProp;
hasInferredTypes = true;
if (!inferredPropType) {
return undefined;
}
const inferredProp = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | prop.flags & optionalMask, prop.name);
inferredProp.declarations = prop.declarations;
inferredProp.type = inferredPropType;
inferredProp.isReadonly = readonlyMask && isReadonlySymbol(prop);
members[prop.name] = inferredProp;
}
let indexInfo = getIndexInfoOfType(source, IndexKind.String);
if (indexInfo) {
const inferredIndexType = inferTargetType(indexInfo.type);
if (inferredIndexType) {
indexInfo = createIndexInfo(inferredIndexType, readonlyMask && indexInfo.isReadonly);
hasInferredTypes = true;
if (!inferredIndexType) {
return undefined;
}
indexInfo = createIndexInfo(inferredIndexType, readonlyMask && indexInfo.isReadonly);
}
return hasInferredTypes ? createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined) : source;
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
function inferTargetType(sourceType: Type): Type {
typeInferences.primary = undefined;
typeInferences.secondary = undefined;
inferTypes(typeParameterArray, typeInferencesArray, sourceType, templateType);
inferTypes(typeVariableArray, typeInferencesArray, sourceType, templateType);
const inferences = typeInferences.primary || typeInferences.secondary;
return inferences && getUnionType(inferences, /*subtypeReduction*/ true);
}
@ -8530,7 +8532,7 @@ namespace ts {
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
}
function inferTypes(typeParameters: Type[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
let sourceStack: Type[];
let targetStack: Type[];
let depth = 0;
@ -8548,7 +8550,7 @@ namespace ts {
}
function inferFromTypes(source: Type, target: Type) {
if (!couldContainTypeParameters(target)) {
if (!couldContainTypeVariables(target)) {
return;
}
if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) {
@ -8598,7 +8600,7 @@ namespace ts {
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
}
}
if (target.flags & (TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {
if (target.flags & TypeFlags.TypeVariable) {
// 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
@ -8608,8 +8610,8 @@ namespace ts {
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
return;
}
for (let i = 0; i < typeParameters.length; i++) {
if (target === typeParameters[i]) {
for (let i = 0; i < typeVariables.length; i++) {
if (target === typeVariables[i]) {
const inferences = typeInferences[i];
if (!inferences.isFixed) {
// Any inferences that are made to a type parameter in a union type are inferior
@ -8643,24 +8645,24 @@ namespace ts {
}
else if (target.flags & TypeFlags.UnionOrIntersection) {
const targetTypes = (<UnionOrIntersectionType>target).types;
let typeParameterCount = 0;
let typeParameter: TypeParameter;
// First infer to each type in union or intersection that isn't a type parameter
let typeVariableCount = 0;
let typeVariable: TypeVariable;
// First infer to each type in union or intersection that isn't a type variable
for (const t of targetTypes) {
if (t.flags & TypeFlags.TypeParameter && contains(typeParameters, t)) {
typeParameter = <TypeParameter>t;
typeParameterCount++;
if (t.flags & TypeFlags.TypeVariable && contains(typeVariables, t)) {
typeVariable = <TypeVariable>t;
typeVariableCount++;
}
else {
inferFromTypes(source, t);
}
}
// Next, if target containings a single naked type parameter, make a secondary inference to that type
// parameter. This gives meaningful results for union types in co-variant positions and intersection
// Next, if target containings a single naked type variable, make a secondary inference to that type
// variable. This gives meaningful results for union types in co-variant positions and intersection
// types in contra-variant positions (such as callback parameters).
if (typeParameterCount === 1) {
if (typeVariableCount === 1) {
inferiority++;
inferFromTypes(source, typeParameter);
inferFromTypes(source, typeVariable);
inferiority--;
}
}
@ -8702,12 +8704,18 @@ namespace ts {
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);
// We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X },
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
// type and then make a secondary inference from that type to T. We make a secondary inference
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
const index = indexOf(typeVariables, (<IndexType>constraintType).type);
if (index >= 0 && !typeInferences[index].isFixed) {
inferFromTypes(inferTypeForIsomorphicMappedType(source, <MappedType>target), typeParameters[index]);
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
if (inferredType) {
inferiority++;
inferFromTypes(inferredType, typeVariables[index]);
inferiority--;
}
}
return;
}
@ -14388,7 +14396,7 @@ namespace ts {
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)) {
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable)) {
error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
return booleanType;
@ -17331,7 +17339,7 @@ namespace ts {
// 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)) {
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable)) {
error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
}

View File

@ -272,7 +272,7 @@ namespace ts {
"es2017": ScriptTarget.ES2017,
"esnext": ScriptTarget.ESNext,
}),
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015,
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_ES2015_ES2016_ES2017_or_ESNEXT,
paramType: Diagnostics.VERSION,
},
{

View File

@ -2473,7 +2473,7 @@
"category": "Message",
"code": 6012
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015'": {
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'": {
"category": "Message",
"code": 6015
},

View File

@ -345,6 +345,7 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
// TypeScript property declarations are elided.
return undefined;
case SyntaxKind.Constructor:
return visitConstructor(<ConstructorDeclaration>node);

View File

@ -2797,6 +2797,7 @@ namespace ts {
UnionOrIntersection = Union | Intersection,
StructuredType = Object | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter | Index,
TypeVariable = TypeParameter | IndexedAccess,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
@ -2907,7 +2908,9 @@ namespace ts {
/* @internal */
resolvedProperties: SymbolTable; // Cache of resolved properties
/* @internal */
couldContainTypeParameters: boolean;
resolvedIndexType: IndexType;
/* @internal */
couldContainTypeVariables: boolean;
}
export interface UnionType extends UnionOrIntersectionType { }
@ -2963,8 +2966,13 @@ namespace ts {
iteratorElementType?: Type;
}
export interface TypeVariable extends Type {
/* @internal */
resolvedIndexType: IndexType;
}
// Type parameters (TypeFlags.TypeParameter)
export interface TypeParameter extends Type {
export interface TypeParameter extends TypeVariable {
constraint: Type; // Constraint
/* @internal */
target?: TypeParameter; // Instantiation target
@ -2973,20 +2981,21 @@ namespace ts {
/* @internal */
resolvedApparentType: Type;
/* @internal */
resolvedIndexType: IndexType;
/* @internal */
isThisType?: boolean;
}
export interface IndexType extends Type {
type: TypeParameter;
}
export interface IndexedAccessType extends Type {
// Indexed access types (TypeFlags.IndexedAccess)
// Possible forms are T[xxx], xxx[T], or xxx[keyof T], where T is a type variable
export interface IndexedAccessType extends TypeVariable {
objectType: Type;
indexType: Type;
}
// keyof T types (TypeFlags.Index)
export interface IndexType extends Type {
type: TypeVariable | UnionOrIntersectionType;
}
export const enum SignatureKind {
Call,
Construct,

View File

@ -118,7 +118,39 @@ function f10(foo: Foo) {
let x = validate(foo); // { a: number, readonly b: string }
let y = clone(foo); // { a?: number, b: string }
let z = validateAndClone(foo); // { a: number, b: string }
}
}
// Repro from #12606
type Func<T> = (...args: any[]) => T;
type Spec<T> = {
[P in keyof T]: Func<T[P]> | Spec<T[P]> ;
};
/**
* Given a spec object recursively mapping properties to functions, creates a function
* producing an object of the same structure, by mapping each property to the result
* of calling its associated function with the supplied arguments.
*/
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
var g1 = applySpec({
sum: (a: any) => 3,
nested: {
mul: (b: any) => "n"
}
});
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });
// Repro from #12633
const foo = <T>(object: T, partial: Partial<T>) => object;
let o = {a: 5, b: 7};
foo(o, {b: 9});
o = foo(o, {b: 9});
//// [isomorphicMappedTypeInference.js]
function box(x) {
@ -210,6 +242,20 @@ function f10(foo) {
var y = clone(foo); // { a?: number, b: string }
var z = validateAndClone(foo); // { a: number, b: string }
}
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
var g1 = applySpec({
sum: function (a) { return 3; },
nested: {
mul: function (b) { return "n"; }
}
});
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
var g2 = applySpec({ foo: { bar: { baz: function (x) { return true; } } } });
// Repro from #12633
var foo = function (object, partial) { return object; };
var o = { a: 5, b: 7 };
foo(o, { b: 9 });
o = foo(o, { b: 9 });
//// [isomorphicMappedTypeInference.d.ts]
@ -254,3 +300,31 @@ declare type Foo = {
readonly b: string;
};
declare function f10(foo: Foo): void;
declare type Func<T> = (...args: any[]) => T;
declare type Spec<T> = {
[P in keyof T]: Func<T[P]> | Spec<T[P]>;
};
/**
* Given a spec object recursively mapping properties to functions, creates a function
* producing an object of the same structure, by mapping each property to the result
* of calling its associated function with the supplied arguments.
*/
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
declare var g1: (...args: any[]) => {
sum: number;
nested: {
mul: string;
};
};
declare var g2: (...args: any[]) => {
foo: {
bar: {
baz: boolean;
};
};
};
declare const foo: <T>(object: T, partial: Partial<T>) => T;
declare let o: {
a: number;
b: number;
};

View File

@ -393,3 +393,97 @@ function f10(foo: Foo) {
>validateAndClone : Symbol(validateAndClone, Decl(isomorphicMappedTypeInference.ts, 107, 69))
>foo : Symbol(foo, Decl(isomorphicMappedTypeInference.ts, 115, 13))
}
// Repro from #12606
type Func<T> = (...args: any[]) => T;
>Func : Symbol(Func, Decl(isomorphicMappedTypeInference.ts, 119, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 123, 10))
>args : Symbol(args, Decl(isomorphicMappedTypeInference.ts, 123, 16))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 123, 10))
type Spec<T> = {
>Spec : Symbol(Spec, Decl(isomorphicMappedTypeInference.ts, 123, 37))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 124, 10))
[P in keyof T]: Func<T[P]> | Spec<T[P]> ;
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 125, 5))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 124, 10))
>Func : Symbol(Func, Decl(isomorphicMappedTypeInference.ts, 119, 1))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 124, 10))
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 125, 5))
>Spec : Symbol(Spec, Decl(isomorphicMappedTypeInference.ts, 123, 37))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 124, 10))
>P : Symbol(P, Decl(isomorphicMappedTypeInference.ts, 125, 5))
};
/**
* Given a spec object recursively mapping properties to functions, creates a function
* producing an object of the same structure, by mapping each property to the result
* of calling its associated function with the supplied arguments.
*/
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
>applySpec : Symbol(applySpec, Decl(isomorphicMappedTypeInference.ts, 126, 2))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 133, 27))
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 133, 30))
>Spec : Symbol(Spec, Decl(isomorphicMappedTypeInference.ts, 123, 37))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 133, 27))
>args : Symbol(args, Decl(isomorphicMappedTypeInference.ts, 133, 46))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 133, 27))
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
var g1 = applySpec({
>g1 : Symbol(g1, Decl(isomorphicMappedTypeInference.ts, 136, 3))
>applySpec : Symbol(applySpec, Decl(isomorphicMappedTypeInference.ts, 126, 2))
sum: (a: any) => 3,
>sum : Symbol(sum, Decl(isomorphicMappedTypeInference.ts, 136, 20))
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 137, 10))
nested: {
>nested : Symbol(nested, Decl(isomorphicMappedTypeInference.ts, 137, 23))
mul: (b: any) => "n"
>mul : Symbol(mul, Decl(isomorphicMappedTypeInference.ts, 138, 13))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 139, 14))
}
});
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });
>g2 : Symbol(g2, Decl(isomorphicMappedTypeInference.ts, 144, 3))
>applySpec : Symbol(applySpec, Decl(isomorphicMappedTypeInference.ts, 126, 2))
>foo : Symbol(foo, Decl(isomorphicMappedTypeInference.ts, 144, 20))
>bar : Symbol(bar, Decl(isomorphicMappedTypeInference.ts, 144, 27))
>baz : Symbol(baz, Decl(isomorphicMappedTypeInference.ts, 144, 34))
>x : Symbol(x, Decl(isomorphicMappedTypeInference.ts, 144, 41))
// Repro from #12633
const foo = <T>(object: T, partial: Partial<T>) => object;
>foo : Symbol(foo, Decl(isomorphicMappedTypeInference.ts, 148, 5))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 148, 13))
>object : Symbol(object, Decl(isomorphicMappedTypeInference.ts, 148, 16))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 148, 13))
>partial : Symbol(partial, Decl(isomorphicMappedTypeInference.ts, 148, 26))
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 148, 13))
>object : Symbol(object, Decl(isomorphicMappedTypeInference.ts, 148, 16))
let o = {a: 5, b: 7};
>o : Symbol(o, Decl(isomorphicMappedTypeInference.ts, 149, 3))
>a : Symbol(a, Decl(isomorphicMappedTypeInference.ts, 149, 9))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 149, 14))
foo(o, {b: 9});
>foo : Symbol(foo, Decl(isomorphicMappedTypeInference.ts, 148, 5))
>o : Symbol(o, Decl(isomorphicMappedTypeInference.ts, 149, 3))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 150, 8))
o = foo(o, {b: 9});
>o : Symbol(o, Decl(isomorphicMappedTypeInference.ts, 149, 3))
>foo : Symbol(foo, Decl(isomorphicMappedTypeInference.ts, 148, 5))
>o : Symbol(o, Decl(isomorphicMappedTypeInference.ts, 149, 3))
>b : Symbol(b, Decl(isomorphicMappedTypeInference.ts, 151, 12))

View File

@ -467,3 +467,121 @@ function f10(foo: Foo) {
>validateAndClone : <T>(obj: { readonly [P in keyof T]?: T[P] | undefined; }) => T
>foo : Foo
}
// Repro from #12606
type Func<T> = (...args: any[]) => T;
>Func : Func<T>
>T : T
>args : any[]
>T : T
type Spec<T> = {
>Spec : Spec<T>
>T : T
[P in keyof T]: Func<T[P]> | Spec<T[P]> ;
>P : P
>T : T
>Func : Func<T>
>T : T
>P : P
>Spec : Spec<T>
>T : T
>P : P
};
/**
* Given a spec object recursively mapping properties to functions, creates a function
* producing an object of the same structure, by mapping each property to the result
* of calling its associated function with the supplied arguments.
*/
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
>applySpec : <T>(obj: Spec<T>) => (...args: any[]) => T
>T : T
>obj : Spec<T>
>Spec : Spec<T>
>T : T
>args : any[]
>T : T
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
var g1 = applySpec({
>g1 : (...args: any[]) => { sum: number; nested: { mul: string; }; }
>applySpec({ sum: (a: any) => 3, nested: { mul: (b: any) => "n" }}) : (...args: any[]) => { sum: number; nested: { mul: string; }; }
>applySpec : <T>(obj: Spec<T>) => (...args: any[]) => T
>{ sum: (a: any) => 3, nested: { mul: (b: any) => "n" }} : { sum: (a: any) => number; nested: { mul: (b: any) => string; }; }
sum: (a: any) => 3,
>sum : (a: any) => number
>(a: any) => 3 : (a: any) => number
>a : any
>3 : 3
nested: {
>nested : { mul: (b: any) => string; }
>{ mul: (b: any) => "n" } : { mul: (b: any) => string; }
mul: (b: any) => "n"
>mul : (b: any) => string
>(b: any) => "n" : (b: any) => string
>b : any
>"n" : "n"
}
});
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });
>g2 : (...args: any[]) => { foo: { bar: { baz: boolean; }; }; }
>applySpec({ foo: { bar: { baz: (x: any) => true } } }) : (...args: any[]) => { foo: { bar: { baz: boolean; }; }; }
>applySpec : <T>(obj: Spec<T>) => (...args: any[]) => T
>{ foo: { bar: { baz: (x: any) => true } } } : { foo: { bar: { baz: (x: any) => boolean; }; }; }
>foo : { bar: { baz: (x: any) => boolean; }; }
>{ bar: { baz: (x: any) => true } } : { bar: { baz: (x: any) => boolean; }; }
>bar : { baz: (x: any) => boolean; }
>{ baz: (x: any) => true } : { baz: (x: any) => boolean; }
>baz : (x: any) => boolean
>(x: any) => true : (x: any) => boolean
>x : any
>true : true
// Repro from #12633
const foo = <T>(object: T, partial: Partial<T>) => object;
>foo : <T>(object: T, partial: Partial<T>) => T
><T>(object: T, partial: Partial<T>) => object : <T>(object: T, partial: Partial<T>) => T
>T : T
>object : T
>T : T
>partial : Partial<T>
>Partial : Partial<T>
>T : T
>object : T
let o = {a: 5, b: 7};
>o : { a: number; b: number; }
>{a: 5, b: 7} : { a: number; b: number; }
>a : number
>5 : 5
>b : number
>7 : 7
foo(o, {b: 9});
>foo(o, {b: 9}) : { a: number; b: number; }
>foo : <T>(object: T, partial: Partial<T>) => T
>o : { a: number; b: number; }
>{b: 9} : { b: number; }
>b : number
>9 : 9
o = foo(o, {b: 9});
>o = foo(o, {b: 9}) : { a: number; b: number; }
>o : { a: number; b: number; }
>foo(o, {b: 9}) : { a: number; b: number; }
>foo : <T>(object: T, partial: Partial<T>) => T
>o : { a: number; b: number; }
>{b: 9} : { b: number; }
>b : number
>9 : 9

View File

@ -219,6 +219,36 @@ function f60<T>(source: T, target: T) {
}
}
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
}
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
let x = func({ a: 1, b: "hello" }, { c: true });
x.a; // number | undefined
x.b; // string | undefined
x.c; // boolean | undefined
}
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
}
// Repros from #12011
class Base {
@ -250,7 +280,91 @@ class OtherPerson {
return getProperty(this, "parts")
}
}
// Modified repro from #12544
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function path(obj: any, ...keys: (string | number)[]): any;
function path(obj: any, ...keys: (string | number)[]): any {
let result = obj;
for (let k of keys) {
result = result[k];
}
return result;
}
type Thing = {
a: { x: number, y: string },
b: boolean
};
function f1(thing: Thing) {
let x1 = path(thing, 'a'); // { x: number, y: string }
let x2 = path(thing, 'a', 'y'); // string
let x3 = path(thing, 'b'); // boolean
let x4 = path(thing, ...['a', 'x']); // any
}
// Repro from comment in #12114
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
(value: T[K1][K2]) => object[key1][key2] = value;
// Modified repro from #12573
declare function one<T>(handler: (t: T) => void): T
var empty = one(() => {}) // inferred as {}, expected
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
declare function on<T>(handlerHash: Handlers<T>): T
var hashOfEmpty1 = on({ test: () => {} }); // {}
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
// Repro from #12624
interface Options1<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component1<Data, Computed> {
constructor(options: Options1<Data, Computed>);
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}
let c1 = new Component1({
data: {
hello: ""
}
});
c1.get("hello");
// Repro from #12625
interface Options2<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component2<Data, Computed> {
constructor(options: Options2<Data, Computed>);
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}
// Repro from #12641
interface R {
p: number;
}
function f<K extends keyof R>(p: K) {
let a: any;
a[p].add; // any
}
//// [keyofAndIndexedAccess.js]
var __extends = (this && this.__extends) || function (d, b) {
@ -397,6 +511,31 @@ function f60(source, target) {
target[k] = source[k];
}
}
function f70(func) {
func('a', 'a');
func('a', 'b');
func('a', 'c');
}
function f71(func) {
var x = func({ a: 1, b: "hello" }, { c: true });
x.a; // number | undefined
x.b; // string | undefined
x.c; // boolean | undefined
}
function f72(func) {
var a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
var b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
var c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f73(func) {
var a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
var b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
var c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f74(func) {
var a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
var b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
}
// Repros from #12011
var Base = (function () {
function Base() {
@ -430,6 +569,41 @@ var OtherPerson = (function () {
};
return OtherPerson;
}());
function path(obj) {
var keys = [];
for (var _i = 1; _i < arguments.length; _i++) {
keys[_i - 1] = arguments[_i];
}
var result = obj;
for (var _a = 0, keys_1 = keys; _a < keys_1.length; _a++) {
var k = keys_1[_a];
result = result[k];
}
return result;
}
function f1(thing) {
var x1 = path(thing, 'a'); // { x: number, y: string }
var x2 = path(thing, 'a', 'y'); // string
var x3 = path(thing, 'b'); // boolean
var x4 = path.apply(void 0, [thing].concat(['a', 'x'])); // any
}
// Repro from comment in #12114
var assignTo2 = function (object, key1, key2) {
return function (value) { return object[key1][key2] = value; };
};
var empty = one(function () { }); // inferred as {}, expected
var hashOfEmpty1 = on({ test: function () { } }); // {}
var hashOfEmpty2 = on({ test: function (x) { } }); // { test: boolean }
var c1 = new Component1({
data: {
hello: ""
}
});
c1.get("hello");
function f(p) {
var a;
a[p].add; // any
}
//// [keyofAndIndexedAccess.d.ts]
@ -537,6 +711,11 @@ declare function f53<T, K extends keyof T>(obj: {
declare function f54<T>(obj: T, key: keyof T): void;
declare function f55<T, K extends keyof T>(obj: T, key: K): void;
declare function f60<T>(source: T, target: T): void;
declare function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void): void;
declare function f71(func: <T, U>(x: T, y: U) => Partial<T & U>): void;
declare function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]): void;
declare function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]): void;
declare function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]): void;
declare class Base {
get<K extends keyof this>(prop: K): this[K];
set<K extends keyof this>(prop: K, value: this[K]): void;
@ -551,3 +730,49 @@ declare class OtherPerson {
constructor(parts: number);
getParts(): number;
}
declare function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
declare function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
declare function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
declare function path(obj: any, ...keys: (string | number)[]): any;
declare type Thing = {
a: {
x: number;
y: string;
};
b: boolean;
};
declare function f1(thing: Thing): void;
declare const assignTo2: <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) => (value: T[K1][K2]) => T[K1][K2];
declare function one<T>(handler: (t: T) => void): T;
declare var empty: {};
declare type Handlers<T> = {
[K in keyof T]: (t: T[K]) => void;
};
declare function on<T>(handlerHash: Handlers<T>): T;
declare var hashOfEmpty1: {};
declare var hashOfEmpty2: {
test: boolean;
};
interface Options1<Data, Computed> {
data?: Data;
computed?: Computed;
}
declare class Component1<Data, Computed> {
constructor(options: Options1<Data, Computed>);
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}
declare let c1: Component1<{
hello: string;
}, {}>;
interface Options2<Data, Computed> {
data?: Data;
computed?: Computed;
}
declare class Component2<Data, Computed> {
constructor(options: Options2<Data, Computed>);
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}
interface R {
p: number;
}
declare function f<K extends keyof R>(p: K): void;

View File

@ -766,85 +766,581 @@ function f60<T>(source: T, target: T) {
}
}
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
>f70 : Symbol(f70, Decl(keyofAndIndexedAccess.ts, 218, 1))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 220, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 220, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 220, 22))
>k1 : Symbol(k1, Decl(keyofAndIndexedAccess.ts, 220, 26))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 220, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 220, 22))
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 220, 44))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 220, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 220, 22))
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 220, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 221, 10))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 221, 18))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 221, 30))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 221, 38))
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 220, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 222, 10))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 222, 18))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 222, 30))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 222, 38))
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 220, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 223, 10))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 223, 18))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 223, 30))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 223, 38))
}
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
>f71 : Symbol(f71, Decl(keyofAndIndexedAccess.ts, 224, 1))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 226, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 226, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 226, 22))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 226, 26))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 226, 20))
>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 226, 31))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 226, 22))
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 226, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 226, 22))
let x = func({ a: 1, b: "hello" }, { c: true });
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 227, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 226, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 227, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 227, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 227, 40))
x.a; // number | undefined
>x.a : Symbol(a)
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 227, 7))
>a : Symbol(a)
x.b; // string | undefined
>x.b : Symbol(b)
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 227, 7))
>b : Symbol(b)
x.c; // boolean | undefined
>x.c : Symbol(c)
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 227, 7))
>c : Symbol(c)
}
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
>f72 : Symbol(f72, Decl(keyofAndIndexedAccess.ts, 231, 1))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 233, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 233, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 233, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 233, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 233, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 233, 22))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 233, 55))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 233, 20))
>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 233, 60))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 233, 22))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 233, 66))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 233, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 233, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 233, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 233, 25))
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 234, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 233, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 234, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 234, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 234, 40))
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 235, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 233, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 235, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 235, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 235, 40))
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 236, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 233, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 236, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 236, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 236, 40))
}
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
>f73 : Symbol(f73, Decl(keyofAndIndexedAccess.ts, 237, 1))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 239, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 239, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 239, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 239, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 239, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 239, 22))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 239, 51))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 239, 20))
>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 239, 56))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 239, 22))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 239, 62))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 239, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 239, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 239, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 239, 25))
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 240, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 239, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 240, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 240, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 240, 40))
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 241, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 239, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 241, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 241, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 241, 40))
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 242, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 239, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 242, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 242, 24))
>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 242, 40))
}
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
>f74 : Symbol(f74, Decl(keyofAndIndexedAccess.ts, 243, 1))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 245, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 245, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 245, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 245, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 245, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 245, 22))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 245, 51))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 245, 20))
>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 245, 56))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 245, 22))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 245, 62))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 245, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 245, 20))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 245, 22))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 245, 25))
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 246, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 245, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 246, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 246, 24))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 246, 40))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 246, 46))
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 247, 7))
>func : Symbol(func, Decl(keyofAndIndexedAccess.ts, 245, 13))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 247, 18))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 247, 24))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 247, 40))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 247, 46))
}
// Repros from #12011
class Base {
>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 218, 1))
>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 248, 1))
get<K extends keyof this>(prop: K) {
>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 222, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 223, 8))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 223, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 223, 8))
>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 252, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 253, 8))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 253, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 253, 8))
return this[prop];
>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 218, 1))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 223, 30))
>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 248, 1))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 253, 30))
}
set<K extends keyof this>(prop: K, value: this[K]) {
>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 225, 5))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 226, 8))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 226, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 226, 8))
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 226, 38))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 226, 8))
>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 255, 5))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 256, 8))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 256, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 256, 8))
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 256, 38))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 256, 8))
this[prop] = value;
>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 218, 1))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 226, 30))
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 226, 38))
>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 248, 1))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 256, 30))
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 256, 38))
}
}
class Person extends Base {
>Person : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 229, 1))
>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 218, 1))
>Person : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 259, 1))
>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 248, 1))
parts: number;
>parts : Symbol(Person.parts, Decl(keyofAndIndexedAccess.ts, 231, 27))
>parts : Symbol(Person.parts, Decl(keyofAndIndexedAccess.ts, 261, 27))
constructor(parts: number) {
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 233, 16))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 263, 16))
super();
>super : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 218, 1))
>super : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 248, 1))
this.set("parts", parts);
>this.set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 225, 5))
>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 229, 1))
>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 225, 5))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 233, 16))
>this.set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 255, 5))
>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 259, 1))
>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 255, 5))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 263, 16))
}
getParts() {
>getParts : Symbol(Person.getParts, Decl(keyofAndIndexedAccess.ts, 236, 5))
>getParts : Symbol(Person.getParts, Decl(keyofAndIndexedAccess.ts, 266, 5))
return this.get("parts")
>this.get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 222, 12))
>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 229, 1))
>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 222, 12))
>this.get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 252, 12))
>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 259, 1))
>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 252, 12))
}
}
class OtherPerson {
>OtherPerson : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 240, 1))
>OtherPerson : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 270, 1))
parts: number;
>parts : Symbol(OtherPerson.parts, Decl(keyofAndIndexedAccess.ts, 242, 19))
>parts : Symbol(OtherPerson.parts, Decl(keyofAndIndexedAccess.ts, 272, 19))
constructor(parts: number) {
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 244, 16))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 274, 16))
setProperty(this, "parts", parts);
>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 81, 1))
>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 240, 1))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 244, 16))
>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 270, 1))
>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 274, 16))
}
getParts() {
>getParts : Symbol(OtherPerson.getParts, Decl(keyofAndIndexedAccess.ts, 246, 5))
>getParts : Symbol(OtherPerson.getParts, Decl(keyofAndIndexedAccess.ts, 276, 5))
return getProperty(this, "parts")
>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 77, 26))
>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 240, 1))
>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 270, 1))
}
}
// Modified repro from #12544
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 284, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 284, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 284, 14))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 284, 37))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 284, 14))
>key1 : Symbol(key1, Decl(keyofAndIndexedAccess.ts, 284, 44))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 284, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 284, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 284, 16))
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 285, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 285, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 285, 14))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 285, 36))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 285, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 285, 16))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 285, 61))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 285, 14))
>key1 : Symbol(key1, Decl(keyofAndIndexedAccess.ts, 285, 68))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 285, 16))
>key2 : Symbol(key2, Decl(keyofAndIndexedAccess.ts, 285, 78))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 285, 36))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 285, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 285, 16))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 285, 36))
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 286, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 286, 36))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 286, 16))
>K3 : Symbol(K3, Decl(keyofAndIndexedAccess.ts, 286, 60))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 286, 16))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 286, 36))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 286, 89))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>key1 : Symbol(key1, Decl(keyofAndIndexedAccess.ts, 286, 96))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 286, 16))
>key2 : Symbol(key2, Decl(keyofAndIndexedAccess.ts, 286, 106))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 286, 36))
>key3 : Symbol(key3, Decl(keyofAndIndexedAccess.ts, 286, 116))
>K3 : Symbol(K3, Decl(keyofAndIndexedAccess.ts, 286, 60))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 286, 14))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 286, 16))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 286, 36))
>K3 : Symbol(K3, Decl(keyofAndIndexedAccess.ts, 286, 60))
function path(obj: any, ...keys: (string | number)[]): any;
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 287, 14))
>keys : Symbol(keys, Decl(keyofAndIndexedAccess.ts, 287, 23))
function path(obj: any, ...keys: (string | number)[]): any {
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 288, 14))
>keys : Symbol(keys, Decl(keyofAndIndexedAccess.ts, 288, 23))
let result = obj;
>result : Symbol(result, Decl(keyofAndIndexedAccess.ts, 289, 7))
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 288, 14))
for (let k of keys) {
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 290, 12))
>keys : Symbol(keys, Decl(keyofAndIndexedAccess.ts, 288, 23))
result = result[k];
>result : Symbol(result, Decl(keyofAndIndexedAccess.ts, 289, 7))
>result : Symbol(result, Decl(keyofAndIndexedAccess.ts, 289, 7))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 290, 12))
}
return result;
>result : Symbol(result, Decl(keyofAndIndexedAccess.ts, 289, 7))
}
type Thing = {
>Thing : Symbol(Thing, Decl(keyofAndIndexedAccess.ts, 294, 1))
a: { x: number, y: string },
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 296, 14))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 297, 8))
>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 297, 19))
b: boolean
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 297, 32))
};
function f1(thing: Thing) {
>f1 : Symbol(f1, Decl(keyofAndIndexedAccess.ts, 299, 2))
>thing : Symbol(thing, Decl(keyofAndIndexedAccess.ts, 302, 12))
>Thing : Symbol(Thing, Decl(keyofAndIndexedAccess.ts, 294, 1))
let x1 = path(thing, 'a'); // { x: number, y: string }
>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 303, 7))
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>thing : Symbol(thing, Decl(keyofAndIndexedAccess.ts, 302, 12))
let x2 = path(thing, 'a', 'y'); // string
>x2 : Symbol(x2, Decl(keyofAndIndexedAccess.ts, 304, 7))
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>thing : Symbol(thing, Decl(keyofAndIndexedAccess.ts, 302, 12))
let x3 = path(thing, 'b'); // boolean
>x3 : Symbol(x3, Decl(keyofAndIndexedAccess.ts, 305, 7))
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>thing : Symbol(thing, Decl(keyofAndIndexedAccess.ts, 302, 12))
let x4 = path(thing, ...['a', 'x']); // any
>x4 : Symbol(x4, Decl(keyofAndIndexedAccess.ts, 306, 7))
>path : Symbol(path, Decl(keyofAndIndexedAccess.ts, 280, 1), Decl(keyofAndIndexedAccess.ts, 284, 62), Decl(keyofAndIndexedAccess.ts, 285, 100), Decl(keyofAndIndexedAccess.ts, 286, 142), Decl(keyofAndIndexedAccess.ts, 287, 59))
>thing : Symbol(thing, Decl(keyofAndIndexedAccess.ts, 302, 12))
}
// Repro from comment in #12114
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
>assignTo2 : Symbol(assignTo2, Decl(keyofAndIndexedAccess.ts, 311, 5))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 311, 19))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 311, 21))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 311, 19))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 311, 41))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 311, 19))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 311, 21))
>object : Symbol(object, Decl(keyofAndIndexedAccess.ts, 311, 66))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 311, 19))
>key1 : Symbol(key1, Decl(keyofAndIndexedAccess.ts, 311, 76))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 311, 21))
>key2 : Symbol(key2, Decl(keyofAndIndexedAccess.ts, 311, 86))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 311, 41))
(value: T[K1][K2]) => object[key1][key2] = value;
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 312, 5))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 311, 19))
>K1 : Symbol(K1, Decl(keyofAndIndexedAccess.ts, 311, 21))
>K2 : Symbol(K2, Decl(keyofAndIndexedAccess.ts, 311, 41))
>object : Symbol(object, Decl(keyofAndIndexedAccess.ts, 311, 66))
>key1 : Symbol(key1, Decl(keyofAndIndexedAccess.ts, 311, 76))
>key2 : Symbol(key2, Decl(keyofAndIndexedAccess.ts, 311, 86))
>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 312, 5))
// Modified repro from #12573
declare function one<T>(handler: (t: T) => void): T
>one : Symbol(one, Decl(keyofAndIndexedAccess.ts, 312, 53))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 316, 21))
>handler : Symbol(handler, Decl(keyofAndIndexedAccess.ts, 316, 24))
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 316, 34))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 316, 21))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 316, 21))
var empty = one(() => {}) // inferred as {}, expected
>empty : Symbol(empty, Decl(keyofAndIndexedAccess.ts, 317, 3))
>one : Symbol(one, Decl(keyofAndIndexedAccess.ts, 312, 53))
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
>Handlers : Symbol(Handlers, Decl(keyofAndIndexedAccess.ts, 317, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 319, 14))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 319, 22))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 319, 14))
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 319, 38))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 319, 14))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 319, 22))
declare function on<T>(handlerHash: Handlers<T>): T
>on : Symbol(on, Decl(keyofAndIndexedAccess.ts, 319, 56))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 320, 20))
>handlerHash : Symbol(handlerHash, Decl(keyofAndIndexedAccess.ts, 320, 23))
>Handlers : Symbol(Handlers, Decl(keyofAndIndexedAccess.ts, 317, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 320, 20))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 320, 20))
var hashOfEmpty1 = on({ test: () => {} }); // {}
>hashOfEmpty1 : Symbol(hashOfEmpty1, Decl(keyofAndIndexedAccess.ts, 321, 3))
>on : Symbol(on, Decl(keyofAndIndexedAccess.ts, 319, 56))
>test : Symbol(test, Decl(keyofAndIndexedAccess.ts, 321, 23))
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
>hashOfEmpty2 : Symbol(hashOfEmpty2, Decl(keyofAndIndexedAccess.ts, 322, 3))
>on : Symbol(on, Decl(keyofAndIndexedAccess.ts, 319, 56))
>test : Symbol(test, Decl(keyofAndIndexedAccess.ts, 322, 23))
>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 322, 31))
// Repro from #12624
interface Options1<Data, Computed> {
>Options1 : Symbol(Options1, Decl(keyofAndIndexedAccess.ts, 322, 52))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 326, 19))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 326, 24))
data?: Data
>data : Symbol(Options1.data, Decl(keyofAndIndexedAccess.ts, 326, 36))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 326, 19))
computed?: Computed;
>computed : Symbol(Options1.computed, Decl(keyofAndIndexedAccess.ts, 327, 15))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 326, 24))
}
declare class Component1<Data, Computed> {
>Component1 : Symbol(Component1, Decl(keyofAndIndexedAccess.ts, 329, 1))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 331, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 331, 30))
constructor(options: Options1<Data, Computed>);
>options : Symbol(options, Decl(keyofAndIndexedAccess.ts, 332, 16))
>Options1 : Symbol(Options1, Decl(keyofAndIndexedAccess.ts, 322, 52))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 331, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 331, 30))
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
>get : Symbol(Component1.get, Decl(keyofAndIndexedAccess.ts, 332, 51))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 333, 8))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 331, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 331, 30))
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 333, 43))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 333, 8))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 331, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 331, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 333, 8))
}
let c1 = new Component1({
>c1 : Symbol(c1, Decl(keyofAndIndexedAccess.ts, 336, 3))
>Component1 : Symbol(Component1, Decl(keyofAndIndexedAccess.ts, 329, 1))
data: {
>data : Symbol(data, Decl(keyofAndIndexedAccess.ts, 336, 25))
hello: ""
>hello : Symbol(hello, Decl(keyofAndIndexedAccess.ts, 337, 11))
}
});
c1.get("hello");
>c1.get : Symbol(Component1.get, Decl(keyofAndIndexedAccess.ts, 332, 51))
>c1 : Symbol(c1, Decl(keyofAndIndexedAccess.ts, 336, 3))
>get : Symbol(Component1.get, Decl(keyofAndIndexedAccess.ts, 332, 51))
// Repro from #12625
interface Options2<Data, Computed> {
>Options2 : Symbol(Options2, Decl(keyofAndIndexedAccess.ts, 342, 16))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 346, 19))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 346, 24))
data?: Data
>data : Symbol(Options2.data, Decl(keyofAndIndexedAccess.ts, 346, 36))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 346, 19))
computed?: Computed;
>computed : Symbol(Options2.computed, Decl(keyofAndIndexedAccess.ts, 347, 15))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 346, 24))
}
declare class Component2<Data, Computed> {
>Component2 : Symbol(Component2, Decl(keyofAndIndexedAccess.ts, 349, 1))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 351, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 351, 30))
constructor(options: Options2<Data, Computed>);
>options : Symbol(options, Decl(keyofAndIndexedAccess.ts, 352, 16))
>Options2 : Symbol(Options2, Decl(keyofAndIndexedAccess.ts, 342, 16))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 351, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 351, 30))
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
>get : Symbol(Component2.get, Decl(keyofAndIndexedAccess.ts, 352, 51))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 353, 8))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 351, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 351, 30))
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 353, 47))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 353, 8))
>Data : Symbol(Data, Decl(keyofAndIndexedAccess.ts, 351, 25))
>Computed : Symbol(Computed, Decl(keyofAndIndexedAccess.ts, 351, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 353, 8))
}
// Repro from #12641
interface R {
>R : Symbol(R, Decl(keyofAndIndexedAccess.ts, 354, 1))
p: number;
>p : Symbol(R.p, Decl(keyofAndIndexedAccess.ts, 358, 13))
}
function f<K extends keyof R>(p: K) {
>f : Symbol(f, Decl(keyofAndIndexedAccess.ts, 360, 1))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 362, 11))
>R : Symbol(R, Decl(keyofAndIndexedAccess.ts, 354, 1))
>p : Symbol(p, Decl(keyofAndIndexedAccess.ts, 362, 30))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 362, 11))
let a: any;
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 363, 7))
a[p].add; // any
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 363, 7))
>p : Symbol(p, Decl(keyofAndIndexedAccess.ts, 362, 30))
}

View File

@ -780,8 +780,8 @@ function f52<T>(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number)
>n : number
const x3 = obj[k];
>x3 : boolean
>obj[k] : boolean
>x3 : { [x: string]: boolean; }[keyof T]
>obj[k] : { [x: string]: boolean; }[keyof T]
>obj : { [x: string]: boolean; }
>k : keyof T
}
@ -826,7 +826,7 @@ function f54<T>(obj: T, key: keyof T) {
>T : T
for (let s in obj[key]) {
>s : string
>s : keyof T[keyof T]
>obj[key] : T[keyof T]
>obj : T
>key : keyof T
@ -851,7 +851,7 @@ function f55<T, K extends keyof T>(obj: T, key: K) {
>K : K
for (let s in obj[key]) {
>s : string
>s : keyof T[K]
>obj[key] : T[K]
>obj : T
>key : K
@ -888,6 +888,264 @@ function f60<T>(source: T, target: T) {
}
}
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
>f70 : (func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) => void
>func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
>T : T
>U : U
>k1 : keyof (T | U)
>T : T
>U : U
>k2 : keyof (T & U)
>T : T
>U : U
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
>func<{ a: any, b: any }, { a: any, c: any }>('a', 'a') : void
>func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
>a : any
>b : any
>a : any
>c : any
>'a' : "a"
>'a' : "a"
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
>func<{ a: any, b: any }, { a: any, c: any }>('a', 'b') : void
>func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
>a : any
>b : any
>a : any
>c : any
>'a' : "a"
>'b' : "b"
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
>func<{ a: any, b: any }, { a: any, c: any }>('a', 'c') : void
>func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
>a : any
>b : any
>a : any
>c : any
>'a' : "a"
>'c' : "c"
}
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
>f71 : (func: <T, U>(x: T, y: U) => Partial<T & U>) => void
>func : <T, U>(x: T, y: U) => Partial<T & U>
>T : T
>U : U
>x : T
>T : T
>y : U
>U : U
>Partial : Partial<T>
>T : T
>U : U
let x = func({ a: 1, b: "hello" }, { c: true });
>x : Partial<{ a: number; b: string; } & { c: boolean; }>
>func({ a: 1, b: "hello" }, { c: true }) : Partial<{ a: number; b: string; } & { c: boolean; }>
>func : <T, U>(x: T, y: U) => Partial<T & U>
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
x.a; // number | undefined
>x.a : number | undefined
>x : Partial<{ a: number; b: string; } & { c: boolean; }>
>a : number | undefined
x.b; // string | undefined
>x.b : string | undefined
>x : Partial<{ a: number; b: string; } & { c: boolean; }>
>b : string | undefined
x.c; // boolean | undefined
>x.c : boolean | undefined
>x : Partial<{ a: number; b: string; } & { c: boolean; }>
>c : boolean | undefined
}
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
>f72 : (func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) => void
>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
>T : T
>U : U
>K : K
>T : T
>U : U
>x : T
>T : T
>y : U
>U : U
>k : K
>K : K
>T : T
>U : U
>K : K
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
>a : number
>func({ a: 1, b: "hello" }, { c: true }, 'a') : number
>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'a' : "a"
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
>b : string
>func({ a: 1, b: "hello" }, { c: true }, 'b') : string
>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'b' : "b"
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
>c : boolean
>func({ a: 1, b: "hello" }, { c: true }, 'c') : boolean
>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'c' : "c"
}
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
>f73 : (func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) => void
>func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
>T : T
>U : U
>K : K
>T : T
>U : U
>x : T
>T : T
>y : U
>U : U
>k : K
>K : K
>T : T
>U : U
>K : K
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
>a : number
>func({ a: 1, b: "hello" }, { c: true }, 'a') : number
>func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'a' : "a"
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
>b : string
>func({ a: 1, b: "hello" }, { c: true }, 'b') : string
>func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'b' : "b"
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
>c : boolean
>func({ a: 1, b: "hello" }, { c: true }, 'c') : boolean
>func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ c: true } : { c: true; }
>c : boolean
>true : true
>'c' : "c"
}
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
>f74 : (func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) => void
>func : <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]
>T : T
>U : U
>K : K
>T : T
>U : U
>x : T
>T : T
>y : U
>U : U
>k : K
>K : K
>T : T
>U : U
>K : K
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
>a : number
>func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a') : number
>func : <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ a: 2, b: true } : { a: number; b: true; }
>a : number
>2 : 2
>b : boolean
>true : true
>'a' : "a"
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
>b : string | boolean
>func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b') : string | boolean
>func : <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]
>{ a: 1, b: "hello" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"hello" : "hello"
>{ a: 2, b: true } : { a: number; b: true; }
>a : number
>2 : 2
>b : boolean
>true : true
>'b' : "b"
}
// Repros from #12011
class Base {
@ -982,3 +1240,350 @@ class OtherPerson {
}
}
// Modified repro from #12544
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>T : T
>K1 : K1
>T : T
>obj : T
>T : T
>key1 : K1
>K1 : K1
>T : T
>K1 : K1
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>T : T
>K1 : K1
>T : T
>K2 : K2
>T : T
>K1 : K1
>obj : T
>T : T
>key1 : K1
>K1 : K1
>key2 : K2
>K2 : K2
>T : T
>K1 : K1
>K2 : K2
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>T : T
>K1 : K1
>T : T
>K2 : K2
>T : T
>K1 : K1
>K3 : K3
>T : T
>K1 : K1
>K2 : K2
>obj : T
>T : T
>key1 : K1
>K1 : K1
>key2 : K2
>K2 : K2
>key3 : K3
>K3 : K3
>T : T
>K1 : K1
>K2 : K2
>K3 : K3
function path(obj: any, ...keys: (string | number)[]): any;
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>obj : any
>keys : (string | number)[]
function path(obj: any, ...keys: (string | number)[]): any {
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>obj : any
>keys : (string | number)[]
let result = obj;
>result : any
>obj : any
for (let k of keys) {
>k : string | number
>keys : (string | number)[]
result = result[k];
>result = result[k] : any
>result : any
>result[k] : any
>result : any
>k : string | number
}
return result;
>result : any
}
type Thing = {
>Thing : Thing
a: { x: number, y: string },
>a : { x: number; y: string; }
>x : number
>y : string
b: boolean
>b : boolean
};
function f1(thing: Thing) {
>f1 : (thing: Thing) => void
>thing : Thing
>Thing : Thing
let x1 = path(thing, 'a'); // { x: number, y: string }
>x1 : { x: number; y: string; }
>path(thing, 'a') : { x: number; y: string; }
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>thing : Thing
>'a' : "a"
let x2 = path(thing, 'a', 'y'); // string
>x2 : string
>path(thing, 'a', 'y') : string
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>thing : Thing
>'a' : "a"
>'y' : "y"
let x3 = path(thing, 'b'); // boolean
>x3 : boolean
>path(thing, 'b') : boolean
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>thing : Thing
>'b' : "b"
let x4 = path(thing, ...['a', 'x']); // any
>x4 : any
>path(thing, ...['a', 'x']) : any
>path : { <T, K1 extends keyof T>(obj: T, key1: K1): T[K1]; <T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2]; <T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; (obj: any, ...keys: (string | number)[]): any; }
>thing : Thing
>...['a', 'x'] : string
>['a', 'x'] : string[]
>'a' : "a"
>'x' : "x"
}
// Repro from comment in #12114
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
>assignTo2 : <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) => (value: T[K1][K2]) => T[K1][K2]
><T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) => (value: T[K1][K2]) => object[key1][key2] = value : <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) => (value: T[K1][K2]) => T[K1][K2]
>T : T
>K1 : K1
>T : T
>K2 : K2
>T : T
>K1 : K1
>object : T
>T : T
>key1 : K1
>K1 : K1
>key2 : K2
>K2 : K2
(value: T[K1][K2]) => object[key1][key2] = value;
>(value: T[K1][K2]) => object[key1][key2] = value : (value: T[K1][K2]) => T[K1][K2]
>value : T[K1][K2]
>T : T
>K1 : K1
>K2 : K2
>object[key1][key2] = value : T[K1][K2]
>object[key1][key2] : T[K1][K2]
>object[key1] : T[K1]
>object : T
>key1 : K1
>key2 : K2
>value : T[K1][K2]
// Modified repro from #12573
declare function one<T>(handler: (t: T) => void): T
>one : <T>(handler: (t: T) => void) => T
>T : T
>handler : (t: T) => void
>t : T
>T : T
>T : T
var empty = one(() => {}) // inferred as {}, expected
>empty : {}
>one(() => {}) : {}
>one : <T>(handler: (t: T) => void) => T
>() => {} : () => void
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
>Handlers : Handlers<T>
>T : T
>K : K
>T : T
>t : T[K]
>T : T
>K : K
declare function on<T>(handlerHash: Handlers<T>): T
>on : <T>(handlerHash: Handlers<T>) => T
>T : T
>handlerHash : Handlers<T>
>Handlers : Handlers<T>
>T : T
>T : T
var hashOfEmpty1 = on({ test: () => {} }); // {}
>hashOfEmpty1 : {}
>on({ test: () => {} }) : {}
>on : <T>(handlerHash: Handlers<T>) => T
>{ test: () => {} } : { test: () => void; }
>test : () => void
>() => {} : () => void
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
>hashOfEmpty2 : { test: boolean; }
>on({ test: (x: boolean) => {} }) : { test: boolean; }
>on : <T>(handlerHash: Handlers<T>) => T
>{ test: (x: boolean) => {} } : { test: (x: boolean) => void; }
>test : (x: boolean) => void
>(x: boolean) => {} : (x: boolean) => void
>x : boolean
// Repro from #12624
interface Options1<Data, Computed> {
>Options1 : Options1<Data, Computed>
>Data : Data
>Computed : Computed
data?: Data
>data : Data | undefined
>Data : Data
computed?: Computed;
>computed : Computed | undefined
>Computed : Computed
}
declare class Component1<Data, Computed> {
>Component1 : Component1<Data, Computed>
>Data : Data
>Computed : Computed
constructor(options: Options1<Data, Computed>);
>options : Options1<Data, Computed>
>Options1 : Options1<Data, Computed>
>Data : Data
>Computed : Computed
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
>get : <K extends keyof (Data & Computed)>(key: K) => (Data & Computed)[K]
>K : K
>Data : Data
>Computed : Computed
>key : K
>K : K
>Data : Data
>Computed : Computed
>K : K
}
let c1 = new Component1({
>c1 : Component1<{ hello: string; }, {}>
>new Component1({ data: { hello: "" }}) : Component1<{ hello: string; }, {}>
>Component1 : typeof Component1
>{ data: { hello: "" }} : { data: { hello: string; }; }
data: {
>data : { hello: string; }
>{ hello: "" } : { hello: string; }
hello: ""
>hello : string
>"" : ""
}
});
c1.get("hello");
>c1.get("hello") : string
>c1.get : <K extends "hello">(key: K) => ({ hello: string; } & {})[K]
>c1 : Component1<{ hello: string; }, {}>
>get : <K extends "hello">(key: K) => ({ hello: string; } & {})[K]
>"hello" : "hello"
// Repro from #12625
interface Options2<Data, Computed> {
>Options2 : Options2<Data, Computed>
>Data : Data
>Computed : Computed
data?: Data
>data : Data | undefined
>Data : Data
computed?: Computed;
>computed : Computed | undefined
>Computed : Computed
}
declare class Component2<Data, Computed> {
>Component2 : Component2<Data, Computed>
>Data : Data
>Computed : Computed
constructor(options: Options2<Data, Computed>);
>options : Options2<Data, Computed>
>Options2 : Options2<Data, Computed>
>Data : Data
>Computed : Computed
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
>get : <K extends keyof Data | keyof Computed>(key: K) => (Data & Computed)[K]
>K : K
>Data : Data
>Computed : Computed
>key : K
>K : K
>Data : Data
>Computed : Computed
>K : K
}
// Repro from #12641
interface R {
>R : R
p: number;
>p : number
}
function f<K extends keyof R>(p: K) {
>f : <K extends "p">(p: K) => void
>K : K
>R : R
>p : K
>K : K
let a: any;
>a : any
a[p].add; // any
>a[p].add : any
>a[p] : any
>a : any
>p : K
>add : any
}

View File

@ -21,9 +21,14 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(64,33): error
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(66,24): error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(67,24): error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'.
Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(72,5): error TS2536: Type 'keyof (T & U)' cannot be used to index type 'T | U'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(76,5): error TS2322: Type 'T | U' is not assignable to type 'T & U'.
Type 'T' is not assignable to type 'T & U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (21 errors) ====
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (24 errors) ====
class Shape {
name: string;
width: number;
@ -135,4 +140,23 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(67,24): error
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'.
!!! error TS2345: Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'.
}
function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
o1[k1];
o1[k2]; // Error
~~~~~~
!!! error TS2536: Type 'keyof (T & U)' cannot be used to index type 'T | U'.
o2[k1];
o2[k2];
o1 = o2;
o2 = o1; // Error
~~
!!! error TS2322: Type 'T | U' is not assignable to type 'T & U'.
!!! error TS2322: Type 'T' is not assignable to type 'T & U'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
k1 = k2; // Error
~~
!!! error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
k2 = k1;
}

View File

@ -66,6 +66,17 @@ function f10(shape: Shape) {
setProperty(shape, "name", "rectangle");
setProperty(shape, "size", 10); // Error
setProperty(shape, cond ? "name" : "size", 10); // Error
}
function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
o1[k1];
o1[k2]; // Error
o2[k1];
o2[k2];
o1 = o2;
o2 = o1; // Error
k1 = k2; // Error
k2 = k1;
}
//// [keyofAndIndexedAccessErrors.js]
@ -88,3 +99,13 @@ function f10(shape) {
setProperty(shape, "size", 10); // Error
setProperty(shape, cond ? "name" : "size", 10); // Error
}
function f20(k1, k2, o1, o2) {
o1[k1];
o1[k2]; // Error
o2[k1];
o2[k2];
o1 = o2;
o2 = o1; // Error
k1 = k2; // Error
k2 = k1;
}

View File

@ -20,9 +20,15 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(60,9): error TS2403: Su
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(61,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type '{ [P in keyof T]: T[P]; }', but here has type '{ readonly [P in keyof T]: T[P]; }'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(62,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type '{ [P in keyof T]: T[P]; }', but here has type '{ readonly [P in keyof T]?: T[P] | undefined; }'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(67,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type '{ [P in keyof T]: T[P]; }', but here has type '{ [P in keyof T]: T[P][]; }'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(76,45): error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'Readonly<{ x: number; y: number; }>'.
Property 'y' is missing in type '{ x: number; }'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(78,59): error TS2345: Argument of type '{ x: number; y: number; z: number; }' is not assignable to parameter of type 'Readonly<{ x: number; y: number; }>'.
Object literal may only specify known properties, and 'z' does not exist in type 'Readonly<{ x: number; y: number; }>'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(84,58): error TS2345: Argument of type '{ x: number; y: number; z: number; }' is not assignable to parameter of type 'Partial<{ x: number; y: number; }>'.
Object literal may only specify known properties, and 'z' does not exist in type 'Partial<{ x: number; y: number; }>'.
==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (14 errors) ====
==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (17 errors) ====
interface Shape {
name: string;
@ -126,4 +132,30 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(67,9): error TS2403: Su
var x: { [P in keyof T]: T[P][] }; // Error
~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type '{ [P in keyof T]: T[P]; }', but here has type '{ [P in keyof T]: T[P][]; }'.
}
// Check that inferences to mapped types are secondary
declare function objAndReadonly<T>(primary: T, secondary: Readonly<T>): T;
declare function objAndPartial<T>(primary: T, secondary: Partial<T>): T;
function f20() {
let x1 = objAndReadonly({ x: 0, y: 0 }, { x: 1 }); // Error
~~~~~~~~
!!! error TS2345: Argument of type '{ x: number; }' is not assignable to parameter of type 'Readonly<{ x: number; y: number; }>'.
!!! error TS2345: Property 'y' is missing in type '{ x: number; }'.
let x2 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
~~~~
!!! error TS2345: Argument of type '{ x: number; y: number; z: number; }' is not assignable to parameter of type 'Readonly<{ x: number; y: number; }>'.
!!! error TS2345: Object literal may only specify known properties, and 'z' does not exist in type 'Readonly<{ x: number; y: number; }>'.
}
function f21() {
let x1 = objAndPartial({ x: 0, y: 0 }, { x: 1 });
let x2 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
~~~~
!!! error TS2345: Argument of type '{ x: number; y: number; z: number; }' is not assignable to parameter of type 'Partial<{ x: number; y: number; }>'.
!!! error TS2345: Object literal may only specify known properties, and 'z' does not exist in type 'Partial<{ x: number; y: number; }>'.
}

View File

@ -66,6 +66,23 @@ function f11<T>() {
function f12<T>() {
var x: { [P in keyof T]: T[P] };
var x: { [P in keyof T]: T[P][] }; // Error
}
// Check that inferences to mapped types are secondary
declare function objAndReadonly<T>(primary: T, secondary: Readonly<T>): T;
declare function objAndPartial<T>(primary: T, secondary: Partial<T>): T;
function f20() {
let x1 = objAndReadonly({ x: 0, y: 0 }, { x: 1 }); // Error
let x2 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}
function f21() {
let x1 = objAndPartial({ x: 0, y: 0 }, { x: 1 });
let x2 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}
//// [mappedTypeErrors.js]
@ -97,6 +114,16 @@ function f12() {
var x;
var x; // Error
}
function f20() {
var x1 = objAndReadonly({ x: 0, y: 0 }, { x: 1 }); // Error
var x2 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1 });
var x3 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}
function f21() {
var x1 = objAndPartial({ x: 0, y: 0 }, { x: 1 });
var x2 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1 });
var x3 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}
//// [mappedTypeErrors.d.ts]
@ -137,3 +164,7 @@ declare function f4<T extends keyof Named>(x: T): void;
declare function f10<T>(): void;
declare function f11<T>(): void;
declare function f12<T>(): void;
declare function objAndReadonly<T>(primary: T, secondary: Readonly<T>): T;
declare function objAndPartial<T>(primary: T, secondary: Partial<T>): T;
declare function f20(): void;
declare function f21(): void;

View File

@ -1,3 +1,4 @@
// @strictNullChecks: true
// @declaration: true
class Shape {
@ -219,6 +220,36 @@ function f60<T>(source: T, target: T) {
}
}
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
}
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
let x = func({ a: 1, b: "hello" }, { c: true });
x.a; // number | undefined
x.b; // string | undefined
x.c; // boolean | undefined
}
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
}
// Repros from #12011
class Base {
@ -250,3 +281,88 @@ class OtherPerson {
return getProperty(this, "parts")
}
}
// Modified repro from #12544
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function path(obj: any, ...keys: (string | number)[]): any;
function path(obj: any, ...keys: (string | number)[]): any {
let result = obj;
for (let k of keys) {
result = result[k];
}
return result;
}
type Thing = {
a: { x: number, y: string },
b: boolean
};
function f1(thing: Thing) {
let x1 = path(thing, 'a'); // { x: number, y: string }
let x2 = path(thing, 'a', 'y'); // string
let x3 = path(thing, 'b'); // boolean
let x4 = path(thing, ...['a', 'x']); // any
}
// Repro from comment in #12114
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
(value: T[K1][K2]) => object[key1][key2] = value;
// Modified repro from #12573
declare function one<T>(handler: (t: T) => void): T
var empty = one(() => {}) // inferred as {}, expected
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
declare function on<T>(handlerHash: Handlers<T>): T
var hashOfEmpty1 = on({ test: () => {} }); // {}
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
// Repro from #12624
interface Options1<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component1<Data, Computed> {
constructor(options: Options1<Data, Computed>);
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}
let c1 = new Component1({
data: {
hello: ""
}
});
c1.get("hello");
// Repro from #12625
interface Options2<Data, Computed> {
data?: Data
computed?: Computed;
}
declare class Component2<Data, Computed> {
constructor(options: Options2<Data, Computed>);
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}
// Repro from #12641
interface R {
p: number;
}
function f<K extends keyof R>(p: K) {
let a: any;
a[p].add; // any
}

View File

@ -65,4 +65,15 @@ function f10(shape: Shape) {
setProperty(shape, "name", "rectangle");
setProperty(shape, "size", 10); // Error
setProperty(shape, cond ? "name" : "size", 10); // Error
}
function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
o1[k1];
o1[k2]; // Error
o2[k1];
o2[k2];
o1 = o2;
o2 = o1; // Error
k1 = k2; // Error
k2 = k1;
}

View File

@ -120,4 +120,36 @@ function f10(foo: Foo) {
let x = validate(foo); // { a: number, readonly b: string }
let y = clone(foo); // { a?: number, b: string }
let z = validateAndClone(foo); // { a: number, b: string }
}
}
// Repro from #12606
type Func<T> = (...args: any[]) => T;
type Spec<T> = {
[P in keyof T]: Func<T[P]> | Spec<T[P]> ;
};
/**
* Given a spec object recursively mapping properties to functions, creates a function
* producing an object of the same structure, by mapping each property to the result
* of calling its associated function with the supplied arguments.
*/
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
var g1 = applySpec({
sum: (a: any) => 3,
nested: {
mul: (b: any) => "n"
}
});
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });
// Repro from #12633
const foo = <T>(object: T, partial: Partial<T>) => object;
let o = {a: 5, b: 7};
foo(o, {b: 9});
o = foo(o, {b: 9});

View File

@ -67,4 +67,21 @@ function f11<T>() {
function f12<T>() {
var x: { [P in keyof T]: T[P] };
var x: { [P in keyof T]: T[P][] }; // Error
}
// Check that inferences to mapped types are secondary
declare function objAndReadonly<T>(primary: T, secondary: Readonly<T>): T;
declare function objAndPartial<T>(primary: T, secondary: Partial<T>): T;
function f20() {
let x1 = objAndReadonly({ x: 0, y: 0 }, { x: 1 }); // Error
let x2 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndReadonly({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}
function f21() {
let x1 = objAndPartial({ x: 0, y: 0 }, { x: 1 });
let x2 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1 });
let x3 = objAndPartial({ x: 0, y: 0 }, { x: 1, y: 1, z: 1 }); // Error
}