Merge pull request #14141 from Microsoft/contextualThisType

Typed 'this' in object literal methods
This commit is contained in:
Anders Hejlsberg
2017-03-06 11:11:40 -10:00
committed by GitHub
47 changed files with 2574 additions and 394 deletions
+211 -154
View File
@@ -259,6 +259,7 @@ namespace ts {
let globalNumberType: ObjectType;
let globalBooleanType: ObjectType;
let globalRegExpType: ObjectType;
let globalThisType: GenericType;
let anyArrayType: Type;
let autoArrayType: Type;
let anyReadonlyArrayType: Type;
@@ -434,6 +435,12 @@ namespace ts {
ResolvedReturnType
}
const enum CheckMode {
Normal = 0, // Normal type checking
SkipContextSensitive = 1, // Skip context sensitive function expressions
Inferential = 2, // Inferential typing
}
const builtinGlobals = createMap<Symbol>();
builtinGlobals.set(undefinedSymbol.name, undefinedSymbol);
@@ -6083,6 +6090,11 @@ namespace ts {
return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalTypeOrUndefined(name: string, arity = 0): ObjectType {
const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined);
return symbol && <GenericType>getTypeOfGlobalSymbol(symbol, arity);
}
/**
* Returns a type that is inside a namespace at the global scope, e.g.
* getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type
@@ -9015,11 +9027,19 @@ namespace ts {
return regularNew;
}
function getWidenedProperty(prop: Symbol): Symbol {
const original = getTypeOfSymbol(prop);
const widened = getWidenedType(original);
return widened === original ? prop : createSymbolWithType(prop, widened);
}
function getWidenedTypeOfObjectLiteral(type: Type): Type {
const members = transformTypeOfMembers(type, prop => {
const widened = getWidenedType(prop);
return prop === widened ? prop : widened;
});
const members = createMap<Symbol>();
for (const prop of getPropertiesOfObjectType(type)) {
// Since get accessors already widen their return value there is no need to
// widen accessor based properties here.
members.set(prop.name, prop.flags & SymbolFlags.Property ? getWidenedProperty(prop) : prop);
};
const stringIndexInfo = getIndexInfoOfType(type, IndexKind.String);
const numberIndexInfo = getIndexInfoOfType(type, IndexKind.Number);
return createAnonymousType(type.symbol, members, emptyArray, emptyArray,
@@ -10065,8 +10085,31 @@ namespace ts {
return f(type) ? type : neverType;
}
function mapType(type: Type, f: (t: Type) => Type): Type {
return type.flags & TypeFlags.Union ? getUnionType(map((<UnionType>type).types, f)) : f(type);
// Apply a mapping function to a type and return the resulting type. If the source type
// is a union type, the mapping function is applied to each constituent type and a union
// of the resulting types is returned.
function mapType(type: Type, mapper: (t: Type) => Type): Type {
if (!(type.flags & TypeFlags.Union)) {
return mapper(type);
}
const types = (<UnionType>type).types;
let mappedType: Type;
let mappedTypes: Type[];
for (const current of types) {
const t = mapper(current);
if (t) {
if (!mappedType) {
mappedType = t;
}
else if (!mappedTypes) {
mappedTypes = [mappedType, t];
}
else {
mappedTypes.push(t);
}
}
}
return mappedTypes ? getUnionType(mappedTypes) : mappedType;
}
function extractTypesOfKind(type: Type, kind: TypeFlags) {
@@ -11502,8 +11545,29 @@ namespace ts {
}
}
function getContainingObjectLiteral(func: FunctionLikeDeclaration) {
return (func.kind === SyntaxKind.MethodDeclaration ||
func.kind === SyntaxKind.GetAccessor ||
func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? <ObjectLiteralExpression>func.parent :
func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? <ObjectLiteralExpression>func.parent.parent :
undefined;
}
function getThisTypeArgument(type: Type): Type {
return getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalThisType ? (<TypeReference>type).typeArguments[0] : undefined;
}
function getThisTypeFromContextualType(type: Type): Type {
return mapType(type, t => {
return t.flags & TypeFlags.Intersection ? forEach((<IntersectionType>t).types, getThisTypeArgument) : getThisTypeArgument(t);
});
}
function getContextualThisParameterType(func: FunctionLikeDeclaration): Type {
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
if (func.kind === SyntaxKind.ArrowFunction) {
return undefined;
}
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
const thisParameter = contextualSignature.thisParameter;
@@ -11512,6 +11576,40 @@ namespace ts {
}
}
}
if (compilerOptions.noImplicitThis) {
const containingLiteral = getContainingObjectLiteral(func);
if (containingLiteral) {
// We have an object literal method. Check if the containing object literal has a contextual type
// that includes a ThisType<T>. If so, T is the contextual type for 'this'. We continue looking in
// any directly enclosing object literals.
const contextualType = getApparentTypeOfContextualType(containingLiteral);
let literal = containingLiteral;
let type = contextualType;
while (type) {
const thisType = getThisTypeFromContextualType(type);
if (thisType) {
return instantiateType(thisType, getContextualMapper(containingLiteral));
}
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
break;
}
literal = <ObjectLiteralExpression>literal.parent.parent;
type = getApparentTypeOfContextualType(literal);
}
// There was no contextual ThisType<T> for the containing object literal, so the contextual type
// for 'this' is the contextual type for the containing object literal or the type of the object
// literal itself.
return contextualType || checkExpressionCached(containingLiteral);
}
// In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the
// contextual type for 'this' is 'obj'.
if (func.parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>func.parent).operatorToken.kind === SyntaxKind.EqualsToken) {
const target = (<BinaryExpression>func.parent).left;
if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) {
return checkExpressionCached((<PropertyAccessExpression | ElementAccessExpression>target).expression);
}
}
}
return undefined;
}
@@ -11710,42 +11808,15 @@ namespace ts {
return undefined;
}
// Apply a mapping function to a contextual type and return the resulting type. If the contextual type
// is a union type, the mapping function is applied to each constituent type and a union of the resulting
// types is returned.
function applyToContextualType(type: Type, mapper: (t: Type) => Type): Type {
if (!(type.flags & TypeFlags.Union)) {
return mapper(type);
}
const types = (<UnionType>type).types;
let mappedType: Type;
let mappedTypes: Type[];
for (const current of types) {
const t = mapper(current);
if (t) {
if (!mappedType) {
mappedType = t;
}
else if (!mappedTypes) {
mappedTypes = [mappedType, t];
}
else {
mappedTypes.push(t);
}
}
}
return mappedTypes ? getUnionType(mappedTypes) : mappedType;
}
function getTypeOfPropertyOfContextualType(type: Type, name: string) {
return applyToContextualType(type, t => {
return mapType(type, t => {
const prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined;
return prop ? getTypeOfSymbol(prop) : undefined;
});
}
function getIndexTypeOfContextualType(type: Type, kind: IndexKind) {
return applyToContextualType(type, t => getIndexTypeOfStructuredType(t, kind));
return mapType(type, t => getIndexTypeOfStructuredType(t, kind));
}
// Return true if the given contextual type is a tuple-like type
@@ -11904,6 +11975,16 @@ namespace ts {
return undefined;
}
function getContextualMapper(node: Node) {
while (node) {
if (node.contextualMapper) {
return node.contextualMapper;
}
node = node.parent;
}
return identityMapper;
}
// If the given type is an object or union type, if that type has a single signature, and if
// that signature is non-generic, return the signature. Otherwise return undefined.
function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
@@ -11994,31 +12075,12 @@ namespace ts {
return result;
}
/**
* Detect if the mapper implies an inference context. Specifically, there are 4 possible values
* for a mapper. Let's go through each one of them:
*
* 1. undefined - this means we are not doing inferential typing, but we may do contextual typing,
* which could cause us to assign a parameter a type
* 2. identityMapper - means we want to avoid assigning a parameter a type, whether or not we are in
* inferential typing (context is undefined for the identityMapper)
* 3. a mapper created by createInferenceMapper - we are doing inferential typing, we want to assign
* types to parameters and fix type parameters (context is defined)
* 4. an instantiation mapper created by createTypeMapper or createTypeEraser - this should never be
* passed as the contextual mapper when checking an expression (context is undefined for these)
*
* isInferentialContext is detecting if we are in case 3
*/
function isInferentialContext(mapper: TypeMapper) {
return mapper && mapper.context;
}
function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type {
function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type {
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.SpreadIncludes);
}
const arrayOrIterableType = checkExpression(node.expression, contextualMapper);
const arrayOrIterableType = checkExpression(node.expression, checkMode);
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterable*/ false);
}
@@ -12027,7 +12089,7 @@ namespace ts {
(node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.EqualsToken);
}
function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type {
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode?: CheckMode): Type {
const elements = node.elements;
let hasSpreadElement = false;
const elementTypes: Type[] = [];
@@ -12046,7 +12108,7 @@ namespace ts {
// get the contextual element type from it. So we do something similar to
// getContextualTypeForElementExpression, which will crucially not error
// if there is no index type / iterated type.
const restArrayType = checkExpression((<SpreadElement>e).expression, contextualMapper);
const restArrayType = checkExpression((<SpreadElement>e).expression, checkMode);
const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false, /*checkAssignability*/ false);
if (restElementType) {
@@ -12054,7 +12116,7 @@ namespace ts {
}
}
else {
const type = checkExpressionForMutableLocation(e, contextualMapper);
const type = checkExpressionForMutableLocation(e, checkMode);
elementTypes.push(type);
}
hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement;
@@ -12169,7 +12231,7 @@ namespace ts {
return createIndexInfo(unionType, /*isReadonly*/ false);
}
function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type {
function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type {
const inDestructuringPattern = isAssignmentTarget(node);
// Grammar checking
checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
@@ -12196,14 +12258,14 @@ namespace ts {
isObjectLiteralMethod(memberDecl)) {
let type: Type;
if (memberDecl.kind === SyntaxKind.PropertyAssignment) {
type = checkPropertyAssignment(<PropertyAssignment>memberDecl, contextualMapper);
type = checkPropertyAssignment(<PropertyAssignment>memberDecl, checkMode);
}
else if (memberDecl.kind === SyntaxKind.MethodDeclaration) {
type = checkObjectLiteralMethod(<MethodDeclaration>memberDecl, contextualMapper);
type = checkObjectLiteralMethod(<MethodDeclaration>memberDecl, checkMode);
}
else {
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
type = checkExpressionForMutableLocation((<ShorthandPropertyAssignment>memberDecl).name, contextualMapper);
type = checkExpressionForMutableLocation((<ShorthandPropertyAssignment>memberDecl).name, checkMode);
}
typeFlags |= type.flags;
@@ -12272,7 +12334,7 @@ namespace ts {
// A set accessor declaration is processed in the same manner
// as an ordinary function declaration with a single parameter and a Void return type.
Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor);
checkAccessorDeclaration(<AccessorDeclaration>memberDecl);
checkNodeDeferred(memberDecl);
}
if (hasDynamicName(memberDecl)) {
@@ -12409,7 +12471,7 @@ namespace ts {
* @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral,
* which also calls getSpreadType.
*/
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, contextualMapper?: TypeMapper) {
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, checkMode?: CheckMode) {
const attributes = openingLikeElement.attributes;
let attributesTable = createMap<Symbol>();
let spread: Type = emptyObjectType;
@@ -12418,7 +12480,7 @@ namespace ts {
const member = attributeDecl.symbol;
if (isJsxAttribute(attributeDecl)) {
const exprType = attributeDecl.initializer ?
checkExpression(attributeDecl.initializer, contextualMapper) :
checkExpression(attributeDecl.initializer, checkMode) :
trueType; // <Elem attr /> is sugar for <Elem attr={true} />
const attributeSymbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
@@ -12489,8 +12551,8 @@ namespace ts {
* (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used)
* @param node a JSXAttributes to be resolved of its type
*/
function checkJsxAttributes(node: JsxAttributes, contextualMapper?: TypeMapper) {
return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, contextualMapper);
function checkJsxAttributes(node: JsxAttributes, checkMode?: CheckMode) {
return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode);
}
function getJsxType(name: string) {
@@ -12983,9 +13045,9 @@ namespace ts {
}
}
function checkJsxExpression(node: JsxExpression, contextualMapper?: TypeMapper) {
function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) {
if (node.expression) {
const type = checkExpression(node.expression, contextualMapper);
const type = checkExpression(node.expression, checkMode);
if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) {
error(node, Diagnostics.JSX_spread_child_must_be_an_array_type, node.toString(), typeToString(type));
}
@@ -14846,9 +14908,9 @@ namespace ts {
return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : neverType;
}
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper, checkMode: CheckMode) {
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
if (isInferentialContext(mapper)) {
if (checkMode === CheckMode.Inferential) {
for (let i = 0; i < len; i++) {
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
if (declaration.type) {
@@ -14862,21 +14924,21 @@ namespace ts {
if (!parameter) {
signature.thisParameter = createSymbolWithType(context.thisParameter, undefined);
}
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper, checkMode);
}
}
for (let i = 0; i < len; i++) {
const parameter = signature.parameters[i];
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
const contextualParameterType = getTypeAtPosition(context, i);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode);
}
}
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
const parameter = lastOrUndefined(signature.parameters);
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode);
}
}
}
@@ -14896,7 +14958,7 @@ namespace ts {
}
}
function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper) {
function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper, checkMode: CheckMode) {
const links = getSymbolLinks(parameter);
if (!links.type) {
links.type = instantiateType(contextualType, mapper);
@@ -14908,7 +14970,7 @@ namespace ts {
}
assignBindingElementTypes(<ParameterDeclaration>parameter.valueDeclaration);
}
else if (isInferentialContext(mapper)) {
else if (checkMode === CheckMode.Inferential) {
// Even if the parameter already has a type, it might be because it was given a type while
// processing the function as an argument to a prior signature during overload resolution.
// If this was the case, it may have caused some type parameters to be fixed. So here,
@@ -14976,7 +15038,7 @@ namespace ts {
return promiseType;
}
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
function getReturnTypeFromBody(func: FunctionLikeDeclaration, checkMode?: CheckMode): Type {
const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
if (!func.body) {
return unknownType;
@@ -14985,7 +15047,7 @@ namespace ts {
const functionFlags = getFunctionFlags(func);
let type: Type;
if (func.body.kind !== SyntaxKind.Block) {
type = checkExpressionCached(<Expression>func.body, contextualMapper);
type = checkExpressionCached(<Expression>func.body, checkMode);
if (functionFlags & FunctionFlags.Async) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
@@ -14997,7 +15059,7 @@ namespace ts {
else {
let types: Type[];
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
types = checkAndAggregateYieldOperandTypes(func, contextualMapper);
types = checkAndAggregateYieldOperandTypes(func, checkMode);
if (types.length === 0) {
const iterableIteratorAny = functionFlags & FunctionFlags.Async
? createAsyncIterableIteratorType(anyType) // AsyncGenerator function
@@ -15010,7 +15072,7 @@ namespace ts {
}
}
else {
types = checkAndAggregateReturnExpressionTypes(func, contextualMapper);
types = checkAndAggregateReturnExpressionTypes(func, checkMode);
if (!types) {
// For an async function, the return type will not be never, but rather a Promise for never.
return functionFlags & FunctionFlags.Async
@@ -15054,13 +15116,13 @@ namespace ts {
: widenedType; // Generator function, AsyncGenerator function, or normal function
}
function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] {
function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] {
const aggregatedTypes: Type[] = [];
const functionFlags = getFunctionFlags(func);
forEachYieldExpression(<Block>func.body, yieldExpression => {
const expr = yieldExpression.expression;
if (expr) {
let type = checkExpressionCached(expr, contextualMapper);
let type = checkExpressionCached(expr, checkMode);
if (yieldExpression.asteriskToken) {
// A yield* expression effectively yields everything that its operand yields
type = checkIteratedTypeOrElementType(type, yieldExpression.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0);
@@ -15100,7 +15162,7 @@ namespace ts {
return true;
}
function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] {
function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] {
const functionFlags = getFunctionFlags(func);
const aggregatedTypes: Type[] = [];
let hasReturnWithNoExpression = functionHasImplicitReturn(func);
@@ -15108,7 +15170,7 @@ namespace ts {
forEachReturnStatement(<Block>func.body, returnStatement => {
const expr = returnStatement.expression;
if (expr) {
let type = checkExpressionCached(expr, contextualMapper);
let type = checkExpressionCached(expr, checkMode);
if (functionFlags & FunctionFlags.Async) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
@@ -15195,7 +15257,7 @@ namespace ts {
}
}
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, checkMode?: CheckMode): Type {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
// Grammar checking
@@ -15205,7 +15267,7 @@ namespace ts {
}
// The identityMapper object is used to indicate that function expressions are wildcards
if (contextualMapper === identityMapper && isContextSensitive(node)) {
if (checkMode === CheckMode.SkipContextSensitive && isContextSensitive(node)) {
checkNodeDeferred(node);
return anyFunctionType;
}
@@ -15213,7 +15275,7 @@ namespace ts {
const links = getNodeLinks(node);
const type = getTypeOfSymbol(node.symbol);
const contextSensitive = isContextSensitive(node);
const mightFixTypeParameters = contextSensitive && isInferentialContext(contextualMapper);
const mightFixTypeParameters = contextSensitive && checkMode === CheckMode.Inferential;
// Check if function expression is contextually typed and assign parameter types if so.
// See the comment in assignTypeToParameterAndFixTypeParameters to understand why we need to
@@ -15229,10 +15291,10 @@ namespace ts {
if (contextualSignature) {
const signature = getSignaturesOfType(type, SignatureKind.Call)[0];
if (contextSensitive) {
assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
assignContextualParameterTypes(signature, contextualSignature, getContextualMapper(node), checkMode);
}
if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) {
const returnType = getReturnTypeFromBody(node, contextualMapper);
const returnType = getReturnTypeFromBody(node, checkMode);
if (!signature.resolvedReturnType) {
signature.resolvedReturnType = returnType;
}
@@ -15608,7 +15670,7 @@ namespace ts {
}
}
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
}
@@ -15619,13 +15681,13 @@ namespace ts {
const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) || unknownType;
const elements = node.elements;
for (let i = 0; i < elements.length; i++) {
checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, contextualMapper);
checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode);
}
return sourceType;
}
function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type,
elementIndex: number, elementType: Type, contextualMapper?: TypeMapper) {
elementIndex: number, elementType: Type, checkMode?: CheckMode) {
const elements = node.elements;
const element = elements[elementIndex];
if (element.kind !== SyntaxKind.OmittedExpression) {
@@ -15637,7 +15699,7 @@ namespace ts {
? getTypeOfPropertyOfType(sourceType, propName)
: elementType;
if (type) {
return checkDestructuringAssignment(element, type, contextualMapper);
return checkDestructuringAssignment(element, type, checkMode);
}
else {
// We still need to check element expression here because we may need to set appropriate flag on the expression
@@ -15661,7 +15723,7 @@ namespace ts {
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
}
else {
return checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
return checkDestructuringAssignment(restExpression, createArrayType(elementType), checkMode);
}
}
}
@@ -15669,7 +15731,7 @@ namespace ts {
return undefined;
}
function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, contextualMapper?: TypeMapper): Type {
function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode): Type {
let target: Expression;
if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) {
const prop = <ShorthandPropertyAssignment>exprOrAssignment;
@@ -15680,7 +15742,7 @@ namespace ts {
!(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) {
sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined);
}
checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, contextualMapper);
checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode);
}
target = (<ShorthandPropertyAssignment>exprOrAssignment).name;
}
@@ -15689,20 +15751,20 @@ namespace ts {
}
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
checkBinaryExpression(<BinaryExpression>target, contextualMapper);
checkBinaryExpression(<BinaryExpression>target, checkMode);
target = (<BinaryExpression>target).left;
}
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType);
}
if (target.kind === SyntaxKind.ArrayLiteralExpression) {
return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, contextualMapper);
return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, checkMode);
}
return checkReferenceAssignment(target, sourceType, contextualMapper);
return checkReferenceAssignment(target, sourceType, checkMode);
}
function checkReferenceAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
const targetType = checkExpression(target, contextualMapper);
function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type {
const targetType = checkExpression(target, checkMode);
const error = target.parent.kind === SyntaxKind.SpreadAssignment ?
Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access :
Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access;
@@ -15790,17 +15852,17 @@ namespace ts {
getUnionType([type1, type2], /*subtypeReduction*/ true);
}
function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) {
return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node);
function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) {
return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node);
}
function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, contextualMapper?: TypeMapper, errorNode?: Node) {
function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node) {
const operator = operatorToken.kind;
if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) {
return checkDestructuringAssignment(left, checkExpression(right, contextualMapper), contextualMapper);
return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode);
}
let leftType = checkExpression(left, contextualMapper);
let rightType = checkExpression(right, contextualMapper);
let leftType = checkExpression(left, checkMode);
let rightType = checkExpression(right, checkMode);
switch (operator) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.AsteriskAsteriskToken:
@@ -16067,10 +16129,10 @@ namespace ts {
return anyType;
}
function checkConditionalExpression(node: ConditionalExpression, contextualMapper?: TypeMapper): Type {
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
checkExpression(node.condition);
const type1 = checkExpression(node.whenTrue, contextualMapper);
const type2 = checkExpression(node.whenFalse, contextualMapper);
const type1 = checkExpression(node.whenTrue, checkMode);
const type2 = checkExpression(node.whenFalse, checkMode);
return getBestChoiceType(type1, type2);
}
@@ -16103,15 +16165,20 @@ namespace ts {
return stringType;
}
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper?: TypeMapper): Type {
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper): Type {
const saveContextualType = node.contextualType;
const saveContextualMapper = node.contextualMapper;
node.contextualType = contextualType;
const result = checkExpression(node, contextualMapper);
node.contextualMapper = contextualMapper;
const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive :
contextualMapper ? CheckMode.Inferential : CheckMode.Normal;
const result = checkExpression(node, checkMode);
node.contextualType = saveContextualType;
node.contextualMapper = saveContextualMapper;
return result;
}
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
function checkExpressionCached(node: Expression, checkMode?: CheckMode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
// When computing a type that we're going to cache, we need to ignore any ongoing control flow
@@ -16119,7 +16186,7 @@ namespace ts {
// to the top of the stack ensures all transient types are computed from a known point.
const saveFlowLoopStart = flowLoopStart;
flowLoopStart = flowLoopCount;
links.resolvedType = checkExpression(node, contextualMapper);
links.resolvedType = checkExpression(node, checkMode);
flowLoopStart = saveFlowLoopStart;
}
return links.resolvedType;
@@ -16154,12 +16221,12 @@ namespace ts {
return false;
}
function checkExpressionForMutableLocation(node: Expression, contextualMapper?: TypeMapper): Type {
const type = checkExpression(node, contextualMapper);
function checkExpressionForMutableLocation(node: Expression, checkMode?: CheckMode): Type {
const type = checkExpression(node, checkMode);
return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type);
}
function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type {
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
// Do not use hasDynamicName here, because that returns false for well known symbols.
// We want to perform checkComputedPropertyName for all computed properties, including
// well known symbols.
@@ -16167,10 +16234,10 @@ namespace ts {
checkComputedPropertyName(<ComputedPropertyName>node.name);
}
return checkExpressionForMutableLocation((<PropertyAssignment>node).initializer, contextualMapper);
return checkExpressionForMutableLocation((<PropertyAssignment>node).initializer, checkMode);
}
function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper?: TypeMapper): Type {
function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type {
// Grammar checking
checkGrammarMethod(node);
@@ -16181,19 +16248,19 @@ namespace ts {
checkComputedPropertyName(<ComputedPropertyName>node.name);
}
const uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
const uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, checkMode);
return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
}
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, contextualMapper?: TypeMapper) {
if (isInferentialContext(contextualMapper)) {
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, checkMode?: CheckMode) {
if (checkMode === CheckMode.Inferential) {
const signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
const contextualType = getApparentTypeOfContextualType(<Expression>node);
if (contextualType) {
const contextualSignature = getSingleCallSignature(contextualType);
if (contextualSignature && !contextualSignature.typeParameters) {
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node)));
}
}
}
@@ -16229,14 +16296,14 @@ namespace ts {
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
// have the wildcard function type; this form of type check is used during overload resolution to exclude
// contextually typed function and arrow expressions in the initial phase.
function checkExpression(node: Expression | QualifiedName, contextualMapper?: TypeMapper): Type {
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type {
let type: Type;
if (node.kind === SyntaxKind.QualifiedName) {
type = checkQualifiedName(<QualifiedName>node);
}
else {
const uninstantiatedType = checkExpressionWorker(<Expression>node, contextualMapper);
type = instantiateTypeWithSingleGenericCallSignature(<Expression>node, uninstantiatedType, contextualMapper);
const uninstantiatedType = checkExpressionWorker(<Expression>node, checkMode);
type = instantiateTypeWithSingleGenericCallSignature(<Expression>node, uninstantiatedType, checkMode);
}
if (isConstEnumObjectType(type)) {
@@ -16256,7 +16323,7 @@ namespace ts {
return type;
}
function checkExpressionWorker(node: Expression, contextualMapper: TypeMapper): Type {
function checkExpressionWorker(node: Expression, checkMode: CheckMode): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
return checkIdentifier(<Identifier>node);
@@ -16278,9 +16345,9 @@ namespace ts {
case SyntaxKind.RegularExpressionLiteral:
return globalRegExpType;
case SyntaxKind.ArrayLiteralExpression:
return checkArrayLiteral(<ArrayLiteralExpression>node, contextualMapper);
return checkArrayLiteral(<ArrayLiteralExpression>node, checkMode);
case SyntaxKind.ObjectLiteralExpression:
return checkObjectLiteral(<ObjectLiteralExpression>node, contextualMapper);
return checkObjectLiteral(<ObjectLiteralExpression>node, checkMode);
case SyntaxKind.PropertyAccessExpression:
return checkPropertyAccessExpression(<PropertyAccessExpression>node);
case SyntaxKind.ElementAccessExpression:
@@ -16291,12 +16358,12 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
return checkExpression((<ParenthesizedExpression>node).expression, contextualMapper);
return checkExpression((<ParenthesizedExpression>node).expression, checkMode);
case SyntaxKind.ClassExpression:
return checkClassExpression(<ClassExpression>node);
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return checkFunctionExpressionOrObjectLiteralMethod(<FunctionExpression>node, contextualMapper);
return checkFunctionExpressionOrObjectLiteralMethod(<FunctionExpression>node, checkMode);
case SyntaxKind.TypeOfExpression:
return checkTypeOfExpression(<TypeOfExpression>node);
case SyntaxKind.TypeAssertionExpression:
@@ -16317,23 +16384,23 @@ namespace ts {
case SyntaxKind.PostfixUnaryExpression:
return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.BinaryExpression:
return checkBinaryExpression(<BinaryExpression>node, contextualMapper);
return checkBinaryExpression(<BinaryExpression>node, checkMode);
case SyntaxKind.ConditionalExpression:
return checkConditionalExpression(<ConditionalExpression>node, contextualMapper);
return checkConditionalExpression(<ConditionalExpression>node, checkMode);
case SyntaxKind.SpreadElement:
return checkSpreadExpression(<SpreadElement>node, contextualMapper);
return checkSpreadExpression(<SpreadElement>node, checkMode);
case SyntaxKind.OmittedExpression:
return undefinedWideningType;
case SyntaxKind.YieldExpression:
return checkYieldExpression(<YieldExpression>node);
case SyntaxKind.JsxExpression:
return checkJsxExpression(<JsxExpression>node, contextualMapper);
return checkJsxExpression(<JsxExpression>node, checkMode);
case SyntaxKind.JsxElement:
return checkJsxElement(<JsxElement>node);
case SyntaxKind.JsxSelfClosingElement:
return checkJsxSelfClosingElement(<JsxSelfClosingElement>node);
case SyntaxKind.JsxAttributes:
return checkJsxAttributes(<JsxAttributes>node, contextualMapper);
return checkJsxAttributes(<JsxAttributes>node, checkMode);
case SyntaxKind.JsxOpeningElement:
Debug.fail("Shouldn't ever directly check a JsxOpeningElement");
}
@@ -16927,13 +16994,8 @@ namespace ts {
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType);
}
}
if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) {
checkSourceElement(node.body);
registerForUnusedIdentifiersCheck(node);
}
else {
checkNodeDeferred(node);
}
checkSourceElement(node.body);
registerForUnusedIdentifiersCheck(node);
}
function checkAccessorDeclarationTypesIdentical(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type, message: DiagnosticMessage) {
@@ -16944,11 +17006,6 @@ namespace ts {
}
}
function checkAccessorDeferred(node: AccessorDeclaration) {
checkSourceElement(node.body);
registerForUnusedIdentifiersCheck(node);
}
function checkMissingDeclaration(node: Node) {
checkDecorators(node);
}
@@ -20615,7 +20672,7 @@ namespace ts {
break;
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
checkAccessorDeferred(<AccessorDeclaration>node);
checkAccessorDeclaration(<AccessorDeclaration>node);
break;
case SyntaxKind.ClassExpression:
checkClassExpressionDeferred(<ClassExpression>node);
@@ -21972,9 +22029,9 @@ namespace ts {
anyArrayType = createArrayType(anyType);
autoArrayType = createArrayType(autoType);
const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined);
globalReadonlyArrayType = symbol && <GenericType>getTypeOfGlobalSymbol(symbol, /*arity*/ 1);
globalReadonlyArrayType = <GenericType>getGlobalTypeOrUndefined("ReadonlyArray", /*arity*/ 1);
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
globalThisType = <GenericType>getGlobalTypeOrUndefined("ThisType", /*arity*/ 1);
}
function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) {
+2 -1
View File
@@ -519,6 +519,8 @@
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
}
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
@@ -963,7 +965,6 @@
export interface Expression extends Node {
_expressionBrand: any;
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
}
export interface OmittedExpression extends Expression {
+8 -3
View File
@@ -147,7 +147,7 @@ interface ObjectConstructor {
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: object | null, properties: PropertyDescriptorMap): any;
create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
@@ -155,14 +155,14 @@ interface ObjectConstructor {
* @param p The property name.
* @param attributes Descriptor for the property. It can be for a data property or an accessor property.
*/
defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType<any>): any;
/**
* Adds one or more properties to an object, and/or modifies attributes of existing properties.
* @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
* @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
*/
defineProperties(o: any, properties: PropertyDescriptorMap): any;
defineProperties(o: any, properties: PropertyDescriptorMap & ThisType<any>): any;
/**
* Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
@@ -1366,6 +1366,11 @@ type Record<K extends string, T> = {
[P in K]: T;
}
/**
* Marker for contextual 'this' type
*/
interface ThisType<T> { }
/**
* Represents a raw buffer of binary data, which is used to store data for the
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
@@ -13,7 +13,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
m(): this is Foo {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -8,7 +8,7 @@ export interface Foo {
export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -16,7 +16,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
m(): this is Foo {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -8,7 +8,7 @@ interface Foo {
export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -9,9 +9,9 @@ function setFunc(v){}
Object.defineProperty({}, "0", <PropertyDescriptor>({
>Object.defineProperty({}, "0", <PropertyDescriptor>({ get: getFunc, set: setFunc, configurable: true })) : any
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
>Object : ObjectConstructor
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
>{} : {}
>"0" : "0"
><PropertyDescriptor>({ get: getFunc, set: setFunc, configurable: true }) : PropertyDescriptor
@@ -1,12 +1,14 @@
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(22,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
The 'this' types of each signature are incompatible.
Type 'void' is not assignable to type 'C'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(26,27): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(34,28): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(38,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(47,20): error TS2339: Property 'length' does not exist on type 'number'.
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ====
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ====
interface I {
n: number;
explicitThis(this: this, m: number): number;
@@ -36,6 +38,8 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error
n: 101,
explicitThis: function (m: number) {
return m + this.n.length; // error, 'length' does not exist on 'number'
~~~~~~
!!! error TS2339: Property 'length' does not exist on type 'number'.
},
implicitThis(m: number): number { return m; }
};
@@ -1,4 +1,5 @@
//// [looseThisTypeInFunctions.ts]
interface I {
n: number;
explicitThis(this: this, m: number): number;
+20 -20
View File
@@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string };
var n = Object.create(null); // object
>n : any
>Object.create(null) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>null : null
var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
>t : any
>Object.create({ a: 1, b: "" }) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{ a: 1, b: "" } : { a: number; b: string; }
>a : number
>1 : 1
@@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
var u = Object.create(union); // object | {a: number, b: string }
>u : any
>Object.create(union) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>union : { a: number; b: string; } | null
var e = Object.create({}); // {}
>e : any
>Object.create({}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{} : {}
var o = Object.create(<object>{}); // object
>o : any
>Object.create(<object>{}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
><object>{} : object
>{} : {}
var a = Object.create(null, {}); // any
>a : any
>Object.create(null, {}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>null : null
>{} : {}
var a = Object.create({ a: 1, b: "" }, {});
>a : any
>Object.create({ a: 1, b: "" }, {}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{ a: 1, b: "" } : { a: number; b: string; }
>a : number
>1 : 1
@@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {});
var a = Object.create(union, {});
>a : any
>Object.create(union, {}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>union : { a: number; b: string; } | null
>{} : {}
var a = Object.create({}, {});
>a : any
>Object.create({}, {}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{} : {}
>{} : {}
var a = Object.create(<object>{}, {});
>a : any
>Object.create(<object>{}, {}) : any
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
><object>{} : object
>{} : {}
>{} : {}
+20 -20
View File
@@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string };
var n = Object.create(null); // any
>n : any
>Object.create(null) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>null : null
var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
>t : any
>Object.create({ a: 1, b: "" }) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{ a: 1, b: "" } : { a: number; b: string; }
>a : number
>1 : 1
@@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
var u = Object.create(union); // {a: number, b: string }
>u : any
>Object.create(union) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>union : { a: number; b: string; }
var e = Object.create({}); // {}
>e : any
>Object.create({}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{} : {}
var o = Object.create(<object>{}); // object
>o : any
>Object.create(<object>{}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
><object>{} : object
>{} : {}
var a = Object.create(null, {}); // any
>a : any
>Object.create(null, {}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>null : null
>{} : {}
var a = Object.create({ a: 1, b: "" }, {});
>a : any
>Object.create({ a: 1, b: "" }, {}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{ a: 1, b: "" } : { a: number; b: string; }
>a : number
>1 : 1
@@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {});
var a = Object.create(union, {});
>a : any
>Object.create(union, {}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>union : { a: number; b: string; }
>{} : {}
var a = Object.create({}, {});
>a : any
>Object.create({}, {}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>{} : {}
>{} : {}
var a = Object.create(<object>{}, {});
>a : any
>Object.create(<object>{}, {}) : any
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
>Object : ObjectConstructor
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
><object>{} : object
>{} : {}
>{} : {}
@@ -5,9 +5,9 @@
Object.defineProperty(obj, "accProperty", <PropertyDescriptor>({
>Object.defineProperty(obj, "accProperty", <PropertyDescriptor>({ get: function () { eval("public = 1;"); return 11; }, set: function (v) { } })) : any
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
>Object : ObjectConstructor
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
>obj : {}
>"accProperty" : "accProperty"
><PropertyDescriptor>({ get: function () { eval("public = 1;"); return 11; }, set: function (v) { } }) : PropertyDescriptor
@@ -1,4 +1,5 @@
//// [selfInLambdas.ts]
interface MouseEvent {
x: number;
y: number;
+37 -29
View File
@@ -1,44 +1,52 @@
=== tests/cases/compiler/selfInLambdas.ts ===
interface MouseEvent {
>MouseEvent : Symbol(MouseEvent, Decl(selfInLambdas.ts, 0, 0))
x: number;
>x : Symbol(MouseEvent.x, Decl(selfInLambdas.ts, 0, 22))
>x : Symbol(MouseEvent.x, Decl(selfInLambdas.ts, 1, 22))
y: number;
>y : Symbol(MouseEvent.y, Decl(selfInLambdas.ts, 1, 14))
>y : Symbol(MouseEvent.y, Decl(selfInLambdas.ts, 2, 14))
}
declare var window: Window;
>window : Symbol(window, Decl(selfInLambdas.ts, 5, 11))
>Window : Symbol(Window, Decl(selfInLambdas.ts, 5, 27))
>window : Symbol(window, Decl(selfInLambdas.ts, 6, 11))
>Window : Symbol(Window, Decl(selfInLambdas.ts, 6, 27))
interface Window {
>Window : Symbol(Window, Decl(selfInLambdas.ts, 5, 27))
>Window : Symbol(Window, Decl(selfInLambdas.ts, 6, 27))
onmousemove: (ev: MouseEvent) => any;
>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18))
>ev : Symbol(ev, Decl(selfInLambdas.ts, 7, 18))
>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18))
>ev : Symbol(ev, Decl(selfInLambdas.ts, 8, 18))
>MouseEvent : Symbol(MouseEvent, Decl(selfInLambdas.ts, 0, 0))
}
var o = {
>o : Symbol(o, Decl(selfInLambdas.ts, 10, 3))
>o : Symbol(o, Decl(selfInLambdas.ts, 11, 3))
counter: 0,
>counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9))
>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9))
start: function() {
>start : Symbol(start, Decl(selfInLambdas.ts, 12, 15))
>start : Symbol(start, Decl(selfInLambdas.ts, 13, 15))
window.onmousemove = () => {
>window.onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18))
>window : Symbol(window, Decl(selfInLambdas.ts, 5, 11))
>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18))
>window.onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18))
>window : Symbol(window, Decl(selfInLambdas.ts, 6, 11))
>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18))
this.counter++
>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9))
>this : Symbol(o, Decl(selfInLambdas.ts, 11, 7))
>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9))
var f = () => this.counter;
>f : Symbol(f, Decl(selfInLambdas.ts, 18, 15))
>f : Symbol(f, Decl(selfInLambdas.ts, 19, 15))
>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9))
>this : Symbol(o, Decl(selfInLambdas.ts, 11, 7))
>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9))
}
@@ -49,39 +57,39 @@ var o = {
class X {
>X : Symbol(X, Decl(selfInLambdas.ts, 24, 1))
>X : Symbol(X, Decl(selfInLambdas.ts, 25, 1))
private value = "value";
>value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9))
>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9))
public foo() {
>foo : Symbol(X.foo, Decl(selfInLambdas.ts, 29, 25))
>foo : Symbol(X.foo, Decl(selfInLambdas.ts, 30, 25))
var outer= () => {
>outer : Symbol(outer, Decl(selfInLambdas.ts, 32, 5))
>outer : Symbol(outer, Decl(selfInLambdas.ts, 33, 5))
var x = this.value;
>x : Symbol(x, Decl(selfInLambdas.ts, 33, 15))
>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9))
>this : Symbol(X, Decl(selfInLambdas.ts, 24, 1))
>value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9))
>x : Symbol(x, Decl(selfInLambdas.ts, 34, 15))
>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9))
>this : Symbol(X, Decl(selfInLambdas.ts, 25, 1))
>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9))
var inner = () => {
>inner : Symbol(inner, Decl(selfInLambdas.ts, 34, 15))
>inner : Symbol(inner, Decl(selfInLambdas.ts, 35, 15))
var y = this.value;
>y : Symbol(y, Decl(selfInLambdas.ts, 35, 19))
>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9))
>this : Symbol(X, Decl(selfInLambdas.ts, 24, 1))
>value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9))
>y : Symbol(y, Decl(selfInLambdas.ts, 36, 19))
>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9))
>this : Symbol(X, Decl(selfInLambdas.ts, 25, 1))
>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9))
}
inner();
>inner : Symbol(inner, Decl(selfInLambdas.ts, 34, 15))
>inner : Symbol(inner, Decl(selfInLambdas.ts, 35, 15))
};
outer();
>outer : Symbol(outer, Decl(selfInLambdas.ts, 32, 5))
>outer : Symbol(outer, Decl(selfInLambdas.ts, 33, 5))
}
}
@@ -1,4 +1,5 @@
=== tests/cases/compiler/selfInLambdas.ts ===
interface MouseEvent {
>MouseEvent : MouseEvent
@@ -43,16 +44,16 @@ var o = {
this.counter++
>this.counter++ : number
>this.counter : any
>this : any
>counter : any
>this.counter : number
>this : { counter: number; start: () => void; }
>counter : number
var f = () => this.counter;
>f : () => any
>() => this.counter : () => any
>this.counter : any
>this : any
>counter : any
>f : () => number
>() => this.counter : () => number
>this.counter : number
>this : { counter: number; start: () => void; }
>counter : number
}
@@ -0,0 +1,28 @@
tests/cases/compiler/thisBinding2.ts(11,11): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
==== tests/cases/compiler/thisBinding2.ts (1 errors) ====
class C {
x: number;
constructor() {
this.x = (() => {
var x = 1;
return this.x;
})();
this.x = function() {
var x = 1;
return this.x;
~~~~
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
}();
}
}
declare function setTimeout(expression: any, msec?: number, language?: any): number;
var messenger = {
message: "Hello World",
start: function () {
return setTimeout(() => { var x = this.message; }, 3000);
}
};
@@ -1,4 +1,5 @@
//// [thisBinding2.ts]
class C {
x: number;
constructor() {
@@ -50,6 +50,9 @@ var messenger = {
return setTimeout(() => { var x = this.message; }, 3000);
>setTimeout : Symbol(setTimeout, Decl(thisBinding2.ts, 12, 1))
>x : Symbol(x, Decl(thisBinding2.ts, 17, 37))
>this.message : Symbol(message, Decl(thisBinding2.ts, 14, 17))
>this : Symbol(messenger, Decl(thisBinding2.ts, 14, 15))
>message : Symbol(message, Decl(thisBinding2.ts, 14, 17))
}
};
+4 -4
View File
@@ -67,10 +67,10 @@ var messenger = {
>setTimeout(() => { var x = this.message; }, 3000) : number
>setTimeout : (expression: any, msec?: number, language?: any) => number
>() => { var x = this.message; } : () => void
>x : any
>this.message : any
>this : any
>message : any
>x : string
>this.message : string
>this : { message: string; start: () => number; }
>message : string
>3000 : 3000
}
};
@@ -1,23 +1,28 @@
tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): error TS2403: Subsequent variable declarations must have the same type. Variable 't' must be of type '{ x: this; y: number; }', but here has type '{ x: MyClass; y: number; }'.
tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(15,5): error TS7023: 'f' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(16,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'.
==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (1 errors) ====
==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (2 errors) ====
class MyClass {
t: number;
fn() {
type ContainingThis = this;
//type of 'this' in an object literal is the containing scope's this
var t = { x: this, y: this.t };
var t: { x: MyClass; y: number };
~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't' must be of type '{ x: this; y: number; }', but here has type '{ x: MyClass; y: number; }'.
var t: { x: ContainingThis; y: number };
}
}
//type of 'this' in an object literal method is the type of the object literal
var obj = {
f() {
~
!!! error TS7023: 'f' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
return this.spaaace;
~~~~~~~
!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'.
}
};
var obj: { f: () => any; };
@@ -1,11 +1,13 @@
//// [thisInObjectLiterals.ts]
class MyClass {
t: number;
fn() {
type ContainingThis = this;
//type of 'this' in an object literal is the containing scope's this
var t = { x: this, y: this.t };
var t: { x: MyClass; y: number };
var t: { x: ContainingThis; y: number };
}
}
@@ -0,0 +1,45 @@
=== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts ===
class MyClass {
>MyClass : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0))
t: number;
>t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15))
fn() {
>fn : Symbol(MyClass.fn, Decl(thisInObjectLiterals.ts, 1, 14))
type ContainingThis = this;
>ContainingThis : Symbol(ContainingThis, Decl(thisInObjectLiterals.ts, 3, 10))
//type of 'this' in an object literal is the containing scope's this
var t = { x: this, y: this.t };
>t : Symbol(t, Decl(thisInObjectLiterals.ts, 6, 11), Decl(thisInObjectLiterals.ts, 7, 11))
>x : Symbol(x, Decl(thisInObjectLiterals.ts, 6, 17))
>this : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0))
>y : Symbol(y, Decl(thisInObjectLiterals.ts, 6, 26))
>this.t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15))
>this : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0))
>t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15))
var t: { x: ContainingThis; y: number };
>t : Symbol(t, Decl(thisInObjectLiterals.ts, 6, 11), Decl(thisInObjectLiterals.ts, 7, 11))
>x : Symbol(x, Decl(thisInObjectLiterals.ts, 7, 16))
>ContainingThis : Symbol(ContainingThis, Decl(thisInObjectLiterals.ts, 3, 10))
>y : Symbol(y, Decl(thisInObjectLiterals.ts, 7, 35))
}
}
//type of 'this' in an object literal method is the type of the object literal
var obj = {
>obj : Symbol(obj, Decl(thisInObjectLiterals.ts, 12, 3), Decl(thisInObjectLiterals.ts, 17, 3))
f() {
>f : Symbol(f, Decl(thisInObjectLiterals.ts, 12, 11))
return this.spaaace;
}
};
var obj: { f: () => any; };
>obj : Symbol(obj, Decl(thisInObjectLiterals.ts, 12, 3), Decl(thisInObjectLiterals.ts, 17, 3))
>f : Symbol(f, Decl(thisInObjectLiterals.ts, 17, 10))
@@ -0,0 +1,50 @@
=== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts ===
class MyClass {
>MyClass : MyClass
t: number;
>t : number
fn() {
>fn : () => void
type ContainingThis = this;
>ContainingThis : this
//type of 'this' in an object literal is the containing scope's this
var t = { x: this, y: this.t };
>t : { x: this; y: number; }
>{ x: this, y: this.t } : { x: this; y: number; }
>x : this
>this : this
>y : number
>this.t : number
>this : this
>t : number
var t: { x: ContainingThis; y: number };
>t : { x: this; y: number; }
>x : this
>ContainingThis : this
>y : number
}
}
//type of 'this' in an object literal method is the type of the object literal
var obj = {
>obj : { f(): any; }
>{ f() { return this.spaaace; }} : { f(): any; }
f() {
>f : () => any
return this.spaaace;
>this.spaaace : any
>this : any
>spaaace : any
}
};
var obj: { f: () => any; };
>obj : { f(): any; }
>f : () => any
@@ -1,9 +1,8 @@
tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(10,9): error TS2682: 'get' and 'set' accessor must have the same 'this' type.
tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(11,9): error TS2682: 'get' and 'set' accessor must have the same 'this' type.
tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(16,22): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
==== tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts (3 errors) ====
==== tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts (2 errors) ====
interface Foo {
n: number;
x: number;
@@ -22,9 +21,6 @@ tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(16,22): er
}
const contextual: Foo = {
n: 16,
// there is no contextual this type from an Foo.x.
get x() { return this.n; }
~~~~
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
}
@@ -13,7 +13,6 @@ const mismatch = {
}
const contextual: Foo = {
n: 16,
// there is no contextual this type from an Foo.x.
get x() { return this.n; }
}
@@ -26,6 +25,5 @@ var mismatch = {
};
var contextual = {
n: 16,
// there is no contextual this type from an Foo.x.
get x() { return this.n; }
};
@@ -0,0 +1,60 @@
tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts(15,5): error TS7010: 'foo', which lacks return-type annotation, implicitly has an 'any' return type.
==== tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts (1 errors) ====
interface IndexedWithThis {
// this is a workaround for React
init?: (this: this) => void;
willDestroy?: (this: any) => void;
[propName: string]: number | string | boolean | symbol | undefined | null | {} | ((this: any, ...args:any[]) => any);
}
interface IndexedWithoutThis {
// this is what React would like to write (and what they write today)
init?: () => void;
willDestroy?: () => void;
[propName: string]: any;
}
interface SimpleInterface {
foo(n: string);
~~~~~~~~~~~~~~~
!!! error TS7010: 'foo', which lacks return-type annotation, implicitly has an 'any' return type.
bar(): number;
}
declare function extend1(args: IndexedWithThis): void;
declare function extend2(args: IndexedWithoutThis): void;
declare function simple(arg: SimpleInterface): void;
extend1({
init() {
this // this: IndexedWithThis because of contextual typing.
// this.mine
this.willDestroy
},
mine: 12,
foo() {
this.url; // this: any because 'foo' matches the string indexer
this.willDestroy;
}
});
extend2({
init() {
this // this: containing object literal type
this.mine
},
mine: 13,
foo() {
this // this: containing object literal type
this.mine
}
});
simple({
foo(n) {
return n.length + this.bar();
},
bar() {
return 14;
}
})
@@ -1,4 +1,5 @@
//// [thisTypeInFunctions2.ts]
interface IndexedWithThis {
// this is a workaround for React
init?: (this: this) => void;
@@ -33,15 +34,13 @@ extend1({
});
extend2({
init() {
this // this: any because the contextual signature of init doesn't specify this' type
this // this: containing object literal type
this.mine
this.willDestroy
},
mine: 13,
foo() {
this // this: any because of the string indexer
this // this: containing object literal type
this.mine
this.willDestroy
}
});
@@ -70,15 +69,13 @@ extend1({
});
extend2({
init: function () {
this; // this: any because the contextual signature of init doesn't specify this' type
this; // this: containing object literal type
this.mine;
this.willDestroy;
},
mine: 13,
foo: function () {
this; // this: any because of the string indexer
this; // this: containing object literal type
this.mine;
this.willDestroy;
}
});
simple({
@@ -89,19 +89,24 @@ extend2({
init() {
>init : Symbol(init, Decl(thisTypeInFunctions2.ts, 32, 9))
this // this: any because the contextual signature of init doesn't specify this' type
this // this: containing object literal type
>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1))
this.mine
this.willDestroy
>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1))
},
mine: 13,
>mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6))
>mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 36, 6))
foo() {
>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 38, 13))
>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 37, 13))
this // this: containing object literal type
>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1))
this // this: any because of the string indexer
this.mine
this.willDestroy
>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1))
}
});
@@ -109,17 +114,20 @@ simple({
>simple : Symbol(simple, Decl(thisTypeInFunctions2.ts, 17, 57))
foo(n) {
>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 46, 8))
>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 47, 8))
>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 44, 8))
>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 45, 8))
return n.length + this.bar();
>n.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 47, 8))
>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 45, 8))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
>this.bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19))
>this : Symbol(SimpleInterface, Decl(thisTypeInFunctions2.ts, 11, 1))
>bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19))
},
bar() {
>bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 49, 6))
>bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 47, 6))
return 14;
}
@@ -92,26 +92,21 @@ extend1({
}
});
extend2({
>extend2({ init() { this // this: any because the contextual signature of init doesn't specify this' type this.mine this.willDestroy }, mine: 13, foo() { this // this: any because of the string indexer this.mine this.willDestroy }}) : void
>extend2({ init() { this // this: containing object literal type this.mine }, mine: 13, foo() { this // this: containing object literal type this.mine }}) : void
>extend2 : (args: IndexedWithoutThis) => void
>{ init() { this // this: any because the contextual signature of init doesn't specify this' type this.mine this.willDestroy }, mine: 13, foo() { this // this: any because of the string indexer this.mine this.willDestroy }} : { init(): void; mine: number; foo(): void; }
>{ init() { this // this: containing object literal type this.mine }, mine: 13, foo() { this // this: containing object literal type this.mine }} : { init(): void; mine: number; foo(): void; }
init() {
>init : () => void
this // this: any because the contextual signature of init doesn't specify this' type
>this : any
this // this: containing object literal type
>this : IndexedWithoutThis
this.mine
>this.mine : any
>this : any
>this : IndexedWithoutThis
>mine : any
this.willDestroy
>this.willDestroy : any
>this : any
>willDestroy : any
},
mine: 13,
>mine : number
@@ -120,39 +115,34 @@ extend2({
foo() {
>foo : () => void
this // this: any because of the string indexer
>this : any
this // this: containing object literal type
>this : IndexedWithoutThis
this.mine
>this.mine : any
>this : any
>this : IndexedWithoutThis
>mine : any
this.willDestroy
>this.willDestroy : any
>this : any
>willDestroy : any
}
});
simple({
>simple({ foo(n) { return n.length + this.bar(); }, bar() { return 14; }}) : void
>simple : (arg: SimpleInterface) => void
>{ foo(n) { return n.length + this.bar(); }, bar() { return 14; }} : { foo(n: string): any; bar(): number; }
>{ foo(n) { return n.length + this.bar(); }, bar() { return 14; }} : { foo(n: string): number; bar(): number; }
foo(n) {
>foo : (n: string) => any
>foo : (n: string) => number
>n : string
return n.length + this.bar();
>n.length + this.bar() : any
>n.length + this.bar() : number
>n.length : number
>n : string
>length : number
>this.bar() : any
>this.bar : any
>this : any
>bar : any
>this.bar() : number
>this.bar : () => number
>this : SimpleInterface
>bar : () => number
},
bar() {
@@ -1,4 +1,5 @@
//// [thisTypeInObjectLiterals.ts]
let o = {
d: "bar",
m() {
@@ -1,80 +1,105 @@
=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts ===
let o = {
>o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 3))
>o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 3))
d: "bar",
>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9))
>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9))
m() {
>m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 1, 13))
>m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 2, 13))
return this.d.length;
>this.d.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9))
>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 7))
>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
},
f: function() {
>f : Symbol(f, Decl(thisTypeInObjectLiterals.ts, 4, 6))
>f : Symbol(f, Decl(thisTypeInObjectLiterals.ts, 5, 6))
return this.d.length;
>this.d.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9))
>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 7))
>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
}
let mutuallyRecursive = {
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3))
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3))
a: 100,
>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25))
>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25))
start() {
>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11))
>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11))
return this.passthrough(this.a);
>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6))
>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23))
>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6))
>this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25))
>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23))
>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25))
},
passthrough(n: number) {
>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16))
>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 16, 16))
return this.sub1(n);
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16))
>this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6))
>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23))
>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 16, 16))
},
sub1(n: number): number {
>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9))
>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9))
if (n > 0) {
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9))
return this.passthrough(n - 1);
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9))
>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6))
>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23))
>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9))
}
return n;
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9))
}
}
var i: number = mutuallyRecursive.start();
>i : Symbol(i, Decl(thisTypeInObjectLiterals.ts, 25, 3))
>mutuallyRecursive.start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11))
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3))
>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11))
>i : Symbol(i, Decl(thisTypeInObjectLiterals.ts, 26, 3))
>mutuallyRecursive.start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11))
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3))
>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11))
interface I {
>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 25, 42))
>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 26, 42))
a: number;
>a : Symbol(I.a, Decl(thisTypeInObjectLiterals.ts, 26, 13))
>a : Symbol(I.a, Decl(thisTypeInObjectLiterals.ts, 27, 13))
start(): number;
>start : Symbol(I.start, Decl(thisTypeInObjectLiterals.ts, 27, 14))
>start : Symbol(I.start, Decl(thisTypeInObjectLiterals.ts, 28, 14))
passthrough(n: number): number;
>passthrough : Symbol(I.passthrough, Decl(thisTypeInObjectLiterals.ts, 28, 20))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 29, 16))
>passthrough : Symbol(I.passthrough, Decl(thisTypeInObjectLiterals.ts, 29, 20))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 30, 16))
sub1(n: number): number;
>sub1 : Symbol(I.sub1, Decl(thisTypeInObjectLiterals.ts, 29, 35))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 30, 9))
>sub1 : Symbol(I.sub1, Decl(thisTypeInObjectLiterals.ts, 30, 35))
>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 31, 9))
}
var impl: I = mutuallyRecursive;
>impl : Symbol(impl, Decl(thisTypeInObjectLiterals.ts, 32, 3))
>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 25, 42))
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3))
>impl : Symbol(impl, Decl(thisTypeInObjectLiterals.ts, 33, 3))
>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 26, 42))
>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3))
@@ -1,66 +1,67 @@
=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts ===
let o = {
>o : { d: string; m(): any; f: () => any; }
>{ d: "bar", m() { return this.d.length; }, f: function() { return this.d.length; }} : { d: string; m(): any; f: () => any; }
>o : { d: string; m(): number; f: () => number; }
>{ d: "bar", m() { return this.d.length; }, f: function() { return this.d.length; }} : { d: string; m(): number; f: () => number; }
d: "bar",
>d : string
>"bar" : "bar"
m() {
>m : () => any
>m : () => number
return this.d.length;
>this.d.length : any
>this.d : any
>this : any
>d : any
>length : any
>this.d.length : number
>this.d : string
>this : { d: string; m(): number; f: () => number; }
>d : string
>length : number
},
f: function() {
>f : () => any
>function() { return this.d.length; } : () => any
>f : () => number
>function() { return this.d.length; } : () => number
return this.d.length;
>this.d.length : any
>this.d : any
>this : any
>d : any
>length : any
>this.d.length : number
>this.d : string
>this : { d: string; m(): number; f: () => number; }
>d : string
>length : number
}
}
let mutuallyRecursive = {
>mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; }
>{ a: 100, start() { return this.passthrough(this.a); }, passthrough(n: number) { return this.sub1(n); }, sub1(n: number): number { if (n > 0) { return this.passthrough(n - 1); } return n; }} : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; }
>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>{ a: 100, start() { return this.passthrough(this.a); }, passthrough(n: number) { return this.sub1(n); }, sub1(n: number): number { if (n > 0) { return this.passthrough(n - 1); } return n; }} : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
a: 100,
>a : number
>100 : 100
start() {
>start : () => any
>start : () => number
return this.passthrough(this.a);
>this.passthrough(this.a) : any
>this.passthrough : any
>this : any
>passthrough : any
>this.a : any
>this : any
>a : any
>this.passthrough(this.a) : number
>this.passthrough : (n: number) => number
>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>passthrough : (n: number) => number
>this.a : number
>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>a : number
},
passthrough(n: number) {
>passthrough : (n: number) => any
>passthrough : (n: number) => number
>n : number
return this.sub1(n);
>this.sub1(n) : any
>this.sub1 : any
>this : any
>sub1 : any
>this.sub1(n) : number
>this.sub1 : (n: number) => number
>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>sub1 : (n: number) => number
>n : number
},
@@ -74,10 +75,10 @@ let mutuallyRecursive = {
>0 : 0
return this.passthrough(n - 1);
>this.passthrough(n - 1) : any
>this.passthrough : any
>this : any
>passthrough : any
>this.passthrough(n - 1) : number
>this.passthrough : (n: number) => number
>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>passthrough : (n: number) => number
>n - 1 : number
>n : number
>1 : 1
@@ -88,10 +89,10 @@ let mutuallyRecursive = {
}
var i: number = mutuallyRecursive.start();
>i : number
>mutuallyRecursive.start() : any
>mutuallyRecursive.start : () => any
>mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; }
>start : () => any
>mutuallyRecursive.start() : number
>mutuallyRecursive.start : () => number
>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
>start : () => number
interface I {
>I : I
@@ -113,5 +114,5 @@ interface I {
var impl: I = mutuallyRecursive;
>impl : I
>I : I
>mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; }
>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; }
@@ -0,0 +1,394 @@
//// [thisTypeInObjectLiterals2.ts]
// In methods of an object literal with no contextual type, 'this' has the type
// of the object literal.
let obj1 = {
a: 1,
f() {
return this.a;
},
b: "hello",
c: {
g() {
this.g();
}
},
get d() {
return this.a;
},
get e() {
return this.b;
},
set e(value) {
this.b = value;
}
};
// In methods of an object literal with a contextual type, 'this' has the
// contextual type.
type Point = {
x: number;
y: number;
z?: number;
moveBy(dx: number, dy: number, dz?: number): void;
}
let p1: Point = {
x: 10,
y: 20,
moveBy(dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
};
declare function f1(p: Point): void;
f1({
x: 10,
y: 20,
moveBy(dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
});
// In methods of an object literal with a contextual type that includes some
// ThisType<T>, 'this' is of type T.
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
}
declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;
let x1 = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
// In methods contained in an object literal with a contextual type that includes
// some ThisType<T>, 'this' is of type T.
type ObjectDescriptor2<D, M> = ThisType<D & M> & {
data?: D;
methods?: M;
}
declare function makeObject2<D, M>(desc: ObjectDescriptor<D, M>): D & M;
let x2 = makeObject2({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
// Check pattern similar to Object.defineProperty and Object.defineProperties
type PropDesc<T> = {
value?: T;
get?(): T;
set?(value: T): void;
}
type PropDescMap<T> = {
[K in keyof T]: PropDesc<T[K]>;
}
declare function defineProp<T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>): T & Record<K, U>;
declare function defineProps<T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>): T & U;
let p10 = defineProp(p1, "foo", { value: 42 });
p10.foo = p10.foo + 1;
let p11 = defineProp(p1, "bar", {
get() {
return this.x;
},
set(value: number) {
this.x = value;
}
});
p11.bar = p11.bar + 1;
let p12 = defineProps(p1, {
foo: {
value: 42
},
bar: {
get(): number {
return this.x;
},
set(value: number) {
this.x = value;
}
}
});
p12.foo = p12.foo + 1;
p12.bar = p12.bar + 1;
// Proof of concept for typing of Vue.js
type Accessors<T> = { [K in keyof T]: (() => T[K]) | Computed<T[K]> };
type Dictionary<T> = { [x: string]: T }
type Computed<T> = {
get?(): T;
set?(value: T): void;
}
type VueOptions<D, M, P> = ThisType<D & M & P> & {
data?: D | (() => D);
methods?: M;
computed?: Accessors<P>;
}
declare const Vue: new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P;
let vue = new Vue({
data: () => ({ x: 1, y: 2 }),
methods: {
f(x: string) {
return this.x;
}
},
computed: {
test(): number {
return this.x;
},
hello: {
get() {
return "hi";
},
set(value: string) {
}
}
}
});
vue;
vue.x;
vue.f("abc");
vue.test;
vue.hello;
//// [thisTypeInObjectLiterals2.js]
// In methods of an object literal with no contextual type, 'this' has the type
// of the object literal.
var obj1 = {
a: 1,
f: function () {
return this.a;
},
b: "hello",
c: {
g: function () {
this.g();
}
},
get d() {
return this.a;
},
get e() {
return this.b;
},
set e(value) {
this.b = value;
}
};
var p1 = {
x: 10,
y: 20,
moveBy: function (dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
};
f1({
x: 10,
y: 20,
moveBy: function (dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
});
var x1 = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy: function (dx, dy) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
var x2 = makeObject2({
data: { x: 0, y: 0 },
methods: {
moveBy: function (dx, dy) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
var p10 = defineProp(p1, "foo", { value: 42 });
p10.foo = p10.foo + 1;
var p11 = defineProp(p1, "bar", {
get: function () {
return this.x;
},
set: function (value) {
this.x = value;
}
});
p11.bar = p11.bar + 1;
var p12 = defineProps(p1, {
foo: {
value: 42
},
bar: {
get: function () {
return this.x;
},
set: function (value) {
this.x = value;
}
}
});
p12.foo = p12.foo + 1;
p12.bar = p12.bar + 1;
var vue = new Vue({
data: function () { return ({ x: 1, y: 2 }); },
methods: {
f: function (x) {
return this.x;
}
},
computed: {
test: function () {
return this.x;
},
hello: {
get: function () {
return "hi";
},
set: function (value) {
}
}
}
});
vue;
vue.x;
vue.f("abc");
vue.test;
vue.hello;
//// [thisTypeInObjectLiterals2.d.ts]
declare let obj1: {
a: number;
f(): number;
b: string;
c: {
g(): void;
};
readonly d: number;
e: string;
};
declare type Point = {
x: number;
y: number;
z?: number;
moveBy(dx: number, dy: number, dz?: number): void;
};
declare let p1: Point;
declare function f1(p: Point): void;
declare type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>;
};
declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;
declare let x1: {
x: number;
y: number;
} & {
moveBy(dx: number, dy: number): void;
};
declare type ObjectDescriptor2<D, M> = ThisType<D & M> & {
data?: D;
methods?: M;
};
declare function makeObject2<D, M>(desc: ObjectDescriptor<D, M>): D & M;
declare let x2: {
x: number;
y: number;
} & {
moveBy(dx: number, dy: number): void;
};
declare type PropDesc<T> = {
value?: T;
get?(): T;
set?(value: T): void;
};
declare type PropDescMap<T> = {
[K in keyof T]: PropDesc<T[K]>;
};
declare function defineProp<T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>): T & Record<K, U>;
declare function defineProps<T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>): T & U;
declare let p10: Point & Record<"foo", number>;
declare let p11: Point & Record<"bar", number>;
declare let p12: Point & {
foo: number;
bar: number;
};
declare type Accessors<T> = {
[K in keyof T]: (() => T[K]) | Computed<T[K]>;
};
declare type Dictionary<T> = {
[x: string]: T;
};
declare type Computed<T> = {
get?(): T;
set?(value: T): void;
};
declare type VueOptions<D, M, P> = ThisType<D & M & P> & {
data?: D | (() => D);
methods?: M;
computed?: Accessors<P>;
};
declare const Vue: new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P;
declare let vue: {
x: number;
y: number;
} & {
f(x: string): number;
} & {
test: number;
hello: string;
};
@@ -0,0 +1,606 @@
=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts ===
// In methods of an object literal with no contextual type, 'this' has the type
// of the object literal.
let obj1 = {
>obj1 : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 3))
a: 1,
>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12))
f() {
>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 5, 9))
return this.a;
>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12))
>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10))
>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12))
},
b: "hello",
>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6))
c: {
>c : Symbol(c, Decl(thisTypeInObjectLiterals2.ts, 9, 15))
g() {
>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8))
this.g();
>this.g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8))
>this : Symbol(__object, Decl(thisTypeInObjectLiterals2.ts, 10, 6))
>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8))
}
},
get d() {
>d : Symbol(d, Decl(thisTypeInObjectLiterals2.ts, 14, 6))
return this.a;
>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12))
>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10))
>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12))
},
get e() {
>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6))
return this.b;
>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6))
>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10))
>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6))
},
set e(value) {
>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10))
this.b = value;
>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6))
>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10))
>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10))
}
};
// In methods of an object literal with a contextual type, 'this' has the
// contextual type.
type Point = {
>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2))
x: number;
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
y: number;
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14))
z?: number;
>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
moveBy(dx: number, dy: number, dz?: number): void;
>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 32, 15))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 33, 11))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 33, 22))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 33, 34))
}
let p1: Point = {
>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3))
>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2))
x: 10,
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 36, 17))
y: 20,
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 37, 10))
moveBy(dx, dy, dz) {
>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 38, 10))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 39, 11))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 39, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18))
this.x += dx;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 39, 11))
this.y += dy;
>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 39, 14))
if (this.z && dz) {
>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18))
this.z += dz;
>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18))
}
}
};
declare function f1(p: Point): void;
>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2))
>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 48, 20))
>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2))
f1({
>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2))
x: 10,
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 50, 4))
y: 20,
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 51, 10))
moveBy(dx, dy, dz) {
>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 52, 10))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18))
this.x += dx;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11))
this.y += dy;
>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14))
if (this.z && dz) {
>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18))
this.z += dz;
>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14))
>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18))
}
}
});
// In methods of an object literal with a contextual type that includes some
// ThisType<T>, 'this' is of type T.
type ObjectDescriptor<D, M> = {
>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24))
data?: D;
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 31))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22))
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 13))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24))
>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24))
}
declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;
>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30))
>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 70, 34))
>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30))
let x1 = makeObject({
>x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 72, 3))
>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1))
data: { x: 0, y: 0 },
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 72, 21))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17))
methods: {
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 73, 25))
moveBy(dx: number, dy: number) {
>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 74, 14))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26))
this.x += dx; // Strongly typed this
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15))
this.y += dy; // Strongly typed this
>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26))
}
}
});
// In methods contained in an object literal with a contextual type that includes
// some ThisType<T>, 'this' is of type T.
type ObjectDescriptor2<D, M> = ThisType<D & M> & {
>ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 80, 3))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25))
>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25))
data?: D;
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 50))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23))
methods?: M;
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 13))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25))
}
declare function makeObject2<D, M>(desc: ObjectDescriptor<D, M>): D & M;
>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31))
>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 90, 35))
>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31))
let x2 = makeObject2({
>x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 92, 3))
>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1))
data: { x: 0, y: 0 },
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 92, 22))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17))
methods: {
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 93, 25))
moveBy(dx: number, dy: number) {
>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 94, 14))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26))
this.x += dx; // Strongly typed this
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11))
>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15))
this.y += dy; // Strongly typed this
>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17))
>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26))
}
}
});
// Check pattern similar to Object.defineProperty and Object.defineProperties
type PropDesc<T> = {
>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14))
value?: T;
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 104, 20))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14))
get?(): T;
>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 105, 14))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14))
set?(value: T): void;
>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 106, 14))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 107, 9))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14))
}
type PropDescMap<T> = {
>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17))
[K in keyof T]: PropDesc<T[K]>;
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17))
>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5))
}
declare function defineProp<T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>): T & Record<K, U>;
>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48))
>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 114, 52))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28))
>name : Symbol(name, Decl(thisTypeInObjectLiterals2.ts, 114, 59))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30))
>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 114, 68))
>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48))
>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28))
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48))
declare function defineProps<T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>): T & U;
>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31))
>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 116, 35))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29))
>descs : Symbol(descs, Decl(thisTypeInObjectLiterals2.ts, 116, 42))
>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31))
>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29))
>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31))
let p10 = defineProp(p1, "foo", { value: 42 });
>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3))
>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1))
>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 118, 33))
p10.foo = p10.foo + 1;
>p10.foo : Symbol(foo)
>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3))
>foo : Symbol(foo)
>p10.foo : Symbol(foo)
>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3))
>foo : Symbol(foo)
let p11 = defineProp(p1, "bar", {
>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3))
>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1))
>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3))
get() {
>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 121, 33))
return this.x;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
},
set(value: number) {
>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 124, 6))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8))
this.x = value;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8))
}
});
p11.bar = p11.bar + 1;
>p11.bar : Symbol(bar)
>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3))
>bar : Symbol(bar)
>p11.bar : Symbol(bar)
>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3))
>bar : Symbol(bar)
let p12 = defineProps(p1, {
>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3))
>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120))
>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3))
foo: {
>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27))
value: 42
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 132, 10))
},
bar: {
>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6))
get(): number {
>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 135, 10))
return this.x;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
},
set(value: number) {
>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 138, 10))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12))
this.x = value;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12))
}
}
});
p12.foo = p12.foo + 1;
>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27))
>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3))
>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27))
>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27))
>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3))
>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27))
p12.bar = p12.bar + 1;
>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6))
>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3))
>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6))
>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6))
>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3))
>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6))
// Proof of concept for typing of Vue.js
type Accessors<T> = { [K in keyof T]: (() => T[K]) | Computed<T[K]> };
>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23))
>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15))
>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23))
type Dictionary<T> = { [x: string]: T }
>Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 149, 70))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 151, 24))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16))
type Computed<T> = {
>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14))
get?(): T;
>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 153, 20))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14))
set?(value: T): void;
>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 154, 14))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 155, 9))
>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14))
}
type VueOptions<D, M, P> = ThisType<D & M & P> & {
>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21))
>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21))
data?: D | (() => D);
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 158, 50))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16))
methods?: M;
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 159, 25))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18))
computed?: Accessors<P>;
>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 160, 16))
>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21))
}
declare const Vue: new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P;
>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29))
>options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 164, 33))
>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29))
>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24))
>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26))
>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29))
let vue = new Vue({
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13))
data: () => ({ x: 1, y: 2 }),
>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 166, 19))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 167, 24))
methods: {
>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 167, 33))
f(x: string) {
>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 169, 10))
return this.x;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
}
},
computed: {
>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 172, 6))
test(): number {
>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15))
return this.x;
>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
},
hello: {
>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10))
get() {
>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 177, 16))
return "hi";
},
set(value: string) {
>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 180, 14))
>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 181, 16))
}
}
}
});
vue;
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
vue.x;
>vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18))
vue.f("abc");
>vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14))
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14))
vue.test;
>vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15))
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15))
vue.hello;
>vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10))
>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3))
>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10))
@@ -0,0 +1,689 @@
=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts ===
// In methods of an object literal with no contextual type, 'this' has the type
// of the object literal.
let obj1 = {
>obj1 : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
>{ a: 1, f() { return this.a; }, b: "hello", c: { g() { this.g(); } }, get d() { return this.a; }, get e() { return this.b; }, set e(value) { this.b = value; }} : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
a: 1,
>a : number
>1 : 1
f() {
>f : () => number
return this.a;
>this.a : number
>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
>a : number
},
b: "hello",
>b : string
>"hello" : "hello"
c: {
>c : { g(): void; }
>{ g() { this.g(); } } : { g(): void; }
g() {
>g : () => void
this.g();
>this.g() : void
>this.g : () => void
>this : { g(): void; }
>g : () => void
}
},
get d() {
>d : number
return this.a;
>this.a : number
>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
>a : number
},
get e() {
>e : string
return this.b;
>this.b : string
>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
>b : string
},
set e(value) {
>e : string
>value : string
this.b = value;
>this.b = value : string
>this.b : string
>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; }
>b : string
>value : string
}
};
// In methods of an object literal with a contextual type, 'this' has the
// contextual type.
type Point = {
>Point : Point
x: number;
>x : number
y: number;
>y : number
z?: number;
>z : number | undefined
moveBy(dx: number, dy: number, dz?: number): void;
>moveBy : (dx: number, dy: number, dz?: number | undefined) => void
>dx : number
>dy : number
>dz : number | undefined
}
let p1: Point = {
>p1 : Point
>Point : Point
>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; }
x: 10,
>x : number
>10 : 10
y: 20,
>y : number
>20 : 20
moveBy(dx, dy, dz) {
>moveBy : (dx: number, dy: number, dz: number | undefined) => void
>dx : number
>dy : number
>dz : number | undefined
this.x += dx;
>this.x += dx : number
>this.x : number
>this : Point
>x : number
>dx : number
this.y += dy;
>this.y += dy : number
>this.y : number
>this : Point
>y : number
>dy : number
if (this.z && dz) {
>this.z && dz : number | undefined
>this.z : number | undefined
>this : Point
>z : number | undefined
>dz : number | undefined
this.z += dz;
>this.z += dz : number
>this.z : number
>this : Point
>z : number
>dz : number
}
}
};
declare function f1(p: Point): void;
>f1 : (p: Point) => void
>p : Point
>Point : Point
f1({
>f1({ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }}) : void
>f1 : (p: Point) => void
>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; }
x: 10,
>x : number
>10 : 10
y: 20,
>y : number
>20 : 20
moveBy(dx, dy, dz) {
>moveBy : (dx: number, dy: number, dz: number | undefined) => void
>dx : number
>dy : number
>dz : number | undefined
this.x += dx;
>this.x += dx : number
>this.x : number
>this : Point
>x : number
>dx : number
this.y += dy;
>this.y += dy : number
>this.y : number
>this : Point
>y : number
>dy : number
if (this.z && dz) {
>this.z && dz : number | undefined
>this.z : number | undefined
>this : Point
>z : number | undefined
>dz : number | undefined
this.z += dz;
>this.z += dz : number
>this.z : number
>this : Point
>z : number
>dz : number
}
}
});
// In methods of an object literal with a contextual type that includes some
// ThisType<T>, 'this' is of type T.
type ObjectDescriptor<D, M> = {
>ObjectDescriptor : ObjectDescriptor<D, M>
>D : D
>M : M
data?: D;
>data : D | undefined
>D : D
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
>methods : (M & ThisType<D & M>) | undefined
>M : M
>ThisType : ThisType<T>
>D : D
>M : M
}
declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;
>makeObject : <D, M>(desc: ObjectDescriptor<D, M>) => D & M
>D : D
>M : M
>desc : ObjectDescriptor<D, M>
>ObjectDescriptor : ObjectDescriptor<D, M>
>D : D
>M : M
>D : D
>M : M
let x1 = makeObject({
>x1 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>makeObject({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>makeObject : <D, M>(desc: ObjectDescriptor<D, M>) => D & M
>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; }
data: { x: 0, y: 0 },
>data : { x: number; y: number; }
>{ x: 0, y: 0 } : { x: number; y: number; }
>x : number
>0 : 0
>y : number
>0 : 0
methods: {
>methods : { moveBy(dx: number, dy: number): void; }
>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; }
moveBy(dx: number, dy: number) {
>moveBy : (dx: number, dy: number) => void
>dx : number
>dy : number
this.x += dx; // Strongly typed this
>this.x += dx : number
>this.x : number
>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>x : number
>dx : number
this.y += dy; // Strongly typed this
>this.y += dy : number
>this.y : number
>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>y : number
>dy : number
}
}
});
// In methods contained in an object literal with a contextual type that includes
// some ThisType<T>, 'this' is of type T.
type ObjectDescriptor2<D, M> = ThisType<D & M> & {
>ObjectDescriptor2 : ObjectDescriptor2<D, M>
>D : D
>M : M
>ThisType : ThisType<T>
>D : D
>M : M
data?: D;
>data : D | undefined
>D : D
methods?: M;
>methods : M | undefined
>M : M
}
declare function makeObject2<D, M>(desc: ObjectDescriptor<D, M>): D & M;
>makeObject2 : <D, M>(desc: ObjectDescriptor<D, M>) => D & M
>D : D
>M : M
>desc : ObjectDescriptor<D, M>
>ObjectDescriptor : ObjectDescriptor<D, M>
>D : D
>M : M
>D : D
>M : M
let x2 = makeObject2({
>x2 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>makeObject2({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>makeObject2 : <D, M>(desc: ObjectDescriptor<D, M>) => D & M
>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; }
data: { x: 0, y: 0 },
>data : { x: number; y: number; }
>{ x: 0, y: 0 } : { x: number; y: number; }
>x : number
>0 : 0
>y : number
>0 : 0
methods: {
>methods : { moveBy(dx: number, dy: number): void; }
>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; }
moveBy(dx: number, dy: number) {
>moveBy : (dx: number, dy: number) => void
>dx : number
>dy : number
this.x += dx; // Strongly typed this
>this.x += dx : number
>this.x : number
>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>x : number
>dx : number
this.y += dy; // Strongly typed this
>this.y += dy : number
>this.y : number
>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }
>y : number
>dy : number
}
}
});
// Check pattern similar to Object.defineProperty and Object.defineProperties
type PropDesc<T> = {
>PropDesc : PropDesc<T>
>T : T
value?: T;
>value : T | undefined
>T : T
get?(): T;
>get : (() => T) | undefined
>T : T
set?(value: T): void;
>set : ((value: T) => void) | undefined
>value : T
>T : T
}
type PropDescMap<T> = {
>PropDescMap : PropDescMap<T>
>T : T
[K in keyof T]: PropDesc<T[K]>;
>K : K
>T : T
>PropDesc : PropDesc<T>
>T : T
>K : K
}
declare function defineProp<T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>): T & Record<K, U>;
>defineProp : <T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>) => T & Record<K, U>
>T : T
>K : K
>U : U
>obj : T
>T : T
>name : K
>K : K
>desc : PropDesc<U> & ThisType<T>
>PropDesc : PropDesc<T>
>U : U
>ThisType : ThisType<T>
>T : T
>T : T
>Record : Record<K, T>
>K : K
>U : U
declare function defineProps<T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>): T & U;
>defineProps : <T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>) => T & U
>T : T
>U : U
>obj : T
>T : T
>descs : PropDescMap<U> & ThisType<T>
>PropDescMap : PropDescMap<T>
>U : U
>ThisType : ThisType<T>
>T : T
>T : T
>U : U
let p10 = defineProp(p1, "foo", { value: 42 });
>p10 : Point & Record<"foo", number>
>defineProp(p1, "foo", { value: 42 }) : Point & Record<"foo", number>
>defineProp : <T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>) => T & Record<K, U>
>p1 : Point
>"foo" : "foo"
>{ value: 42 } : { value: number; }
>value : number
>42 : 42
p10.foo = p10.foo + 1;
>p10.foo = p10.foo + 1 : number
>p10.foo : number
>p10 : Point & Record<"foo", number>
>foo : number
>p10.foo + 1 : number
>p10.foo : number
>p10 : Point & Record<"foo", number>
>foo : number
>1 : 1
let p11 = defineProp(p1, "bar", {
>p11 : Point & Record<"bar", number>
>defineProp(p1, "bar", { get() { return this.x; }, set(value: number) { this.x = value; }}) : Point & Record<"bar", number>
>defineProp : <T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>) => T & Record<K, U>
>p1 : Point
>"bar" : "bar"
>{ get() { return this.x; }, set(value: number) { this.x = value; }} : { get(): number; set(value: number): void; }
get() {
>get : () => number
return this.x;
>this.x : number
>this : Point
>x : number
},
set(value: number) {
>set : (value: number) => void
>value : number
this.x = value;
>this.x = value : number
>this.x : number
>this : Point
>x : number
>value : number
}
});
p11.bar = p11.bar + 1;
>p11.bar = p11.bar + 1 : number
>p11.bar : number
>p11 : Point & Record<"bar", number>
>bar : number
>p11.bar + 1 : number
>p11.bar : number
>p11 : Point & Record<"bar", number>
>bar : number
>1 : 1
let p12 = defineProps(p1, {
>p12 : Point & { foo: number; bar: number; }
>defineProps(p1, { foo: { value: 42 }, bar: { get(): number { return this.x; }, set(value: number) { this.x = value; } }}) : Point & { foo: number; bar: number; }
>defineProps : <T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>) => T & U
>p1 : Point
>{ foo: { value: 42 }, bar: { get(): number { return this.x; }, set(value: number) { this.x = value; } }} : { foo: { value: number; }; bar: { get(): number; set(value: number): void; }; }
foo: {
>foo : { value: number; }
>{ value: 42 } : { value: number; }
value: 42
>value : number
>42 : 42
},
bar: {
>bar : { get(): number; set(value: number): void; }
>{ get(): number { return this.x; }, set(value: number) { this.x = value; } } : { get(): number; set(value: number): void; }
get(): number {
>get : () => number
return this.x;
>this.x : number
>this : Point
>x : number
},
set(value: number) {
>set : (value: number) => void
>value : number
this.x = value;
>this.x = value : number
>this.x : number
>this : Point
>x : number
>value : number
}
}
});
p12.foo = p12.foo + 1;
>p12.foo = p12.foo + 1 : number
>p12.foo : number
>p12 : Point & { foo: number; bar: number; }
>foo : number
>p12.foo + 1 : number
>p12.foo : number
>p12 : Point & { foo: number; bar: number; }
>foo : number
>1 : 1
p12.bar = p12.bar + 1;
>p12.bar = p12.bar + 1 : number
>p12.bar : number
>p12 : Point & { foo: number; bar: number; }
>bar : number
>p12.bar + 1 : number
>p12.bar : number
>p12 : Point & { foo: number; bar: number; }
>bar : number
>1 : 1
// Proof of concept for typing of Vue.js
type Accessors<T> = { [K in keyof T]: (() => T[K]) | Computed<T[K]> };
>Accessors : Accessors<T>
>T : T
>K : K
>T : T
>T : T
>K : K
>Computed : Computed<T>
>T : T
>K : K
type Dictionary<T> = { [x: string]: T }
>Dictionary : Dictionary<T>
>T : T
>x : string
>T : T
type Computed<T> = {
>Computed : Computed<T>
>T : T
get?(): T;
>get : (() => T) | undefined
>T : T
set?(value: T): void;
>set : ((value: T) => void) | undefined
>value : T
>T : T
}
type VueOptions<D, M, P> = ThisType<D & M & P> & {
>VueOptions : VueOptions<D, M, P>
>D : D
>M : M
>P : P
>ThisType : ThisType<T>
>D : D
>M : M
>P : P
data?: D | (() => D);
>data : D | (() => D) | undefined
>D : D
>D : D
methods?: M;
>methods : M | undefined
>M : M
computed?: Accessors<P>;
>computed : Accessors<P> | undefined
>Accessors : Accessors<T>
>P : P
}
declare const Vue: new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P;
>Vue : new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P
>D : D
>M : M
>P : P
>options : VueOptions<D, M, P>
>VueOptions : VueOptions<D, M, P>
>D : D
>M : M
>P : P
>D : D
>M : M
>P : P
let vue = new Vue({
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>new Vue({ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }}) : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>Vue : new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P
>{ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }} : { data: () => { x: number; y: number; }; methods: { f(x: string): number; }; computed: { test(): number; hello: { get(): string; set(value: string): void; }; }; }
data: () => ({ x: 1, y: 2 }),
>data : () => { x: number; y: number; }
>() => ({ x: 1, y: 2 }) : () => { x: number; y: number; }
>({ x: 1, y: 2 }) : { x: number; y: number; }
>{ x: 1, y: 2 } : { x: number; y: number; }
>x : number
>1 : 1
>y : number
>2 : 2
methods: {
>methods : { f(x: string): number; }
>{ f(x: string) { return this.x; } } : { f(x: string): number; }
f(x: string) {
>f : (x: string) => number
>x : string
return this.x;
>this.x : number
>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>x : number
}
},
computed: {
>computed : { test(): number; hello: { get(): string; set(value: string): void; }; }
>{ test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } } : { test(): number; hello: { get(): string; set(value: string): void; }; }
test(): number {
>test : () => number
return this.x;
>this.x : number
>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>x : number
},
hello: {
>hello : { get(): string; set(value: string): void; }
>{ get() { return "hi"; }, set(value: string) { } } : { get(): string; set(value: string): void; }
get() {
>get : () => string
return "hi";
>"hi" : "hi"
},
set(value: string) {
>set : (value: string) => void
>value : string
}
}
}
});
vue;
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
vue.x;
>vue.x : number
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>x : number
vue.f("abc");
>vue.f("abc") : number
>vue.f : (x: string) => number
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>f : (x: string) => number
>"abc" : "abc"
vue.test;
>vue.test : number
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>test : number
vue.hello;
>vue.hello : string
>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; }
>hello : string
@@ -1,10 +0,0 @@
// @noImplicitThis: true
let o = {
d: this, // error, this: any
m() {
return this.d.length; // error, this: any
},
f: function() {
return this.d.length; // error, this: any
}
}
+3
View File
@@ -1,3 +1,6 @@
// @noImplicitAny: true
// @noImplicitThis: true
interface MouseEvent {
x: number;
y: number;
+3
View File
@@ -1,3 +1,6 @@
// @noImplicitAny: true
// @noImplicitThis: true
class C {
x: number;
constructor() {
@@ -9,7 +9,7 @@ export interface Foo {
export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -9,7 +9,7 @@ interface Foo {
export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
@@ -1,10 +1,14 @@
// @noImplicitAny: true
// @noImplicitThis: true
class MyClass {
t: number;
fn() {
type ContainingThis = this;
//type of 'this' in an object literal is the containing scope's this
var t = { x: this, y: this.t };
var t: { x: MyClass; y: number };
var t: { x: ContainingThis; y: number };
}
}
@@ -1,3 +1,6 @@
// @noImplicitAny: true
// @noImplicitThis: true
interface I {
n: number;
explicitThis(this: this, m: number): number;
@@ -15,6 +15,5 @@ const mismatch = {
}
const contextual: Foo = {
n: 16,
// there is no contextual this type from an Foo.x.
get x() { return this.n; }
}
@@ -1,3 +1,6 @@
// @noImplicitAny: true
// @noImplicitThis: true
interface IndexedWithThis {
// this is a workaround for React
init?: (this: this) => void;
@@ -32,15 +35,13 @@ extend1({
});
extend2({
init() {
this // this: any because the contextual signature of init doesn't specify this' type
this // this: containing object literal type
this.mine
this.willDestroy
},
mine: 13,
foo() {
this // this: any because of the string indexer
this // this: containing object literal type
this.mine
this.willDestroy
}
});
@@ -1,3 +1,6 @@
// @noImplicitAny: true
// @noImplicitThis: true
let o = {
d: "bar",
m() {
@@ -0,0 +1,197 @@
// @declaration: true
// @strictNullChecks: true
// @noImplicitAny: true
// @noImplicitThis: true
// @target: es5
// In methods of an object literal with no contextual type, 'this' has the type
// of the object literal.
let obj1 = {
a: 1,
f() {
return this.a;
},
b: "hello",
c: {
g() {
this.g();
}
},
get d() {
return this.a;
},
get e() {
return this.b;
},
set e(value) {
this.b = value;
}
};
// In methods of an object literal with a contextual type, 'this' has the
// contextual type.
type Point = {
x: number;
y: number;
z?: number;
moveBy(dx: number, dy: number, dz?: number): void;
}
let p1: Point = {
x: 10,
y: 20,
moveBy(dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
};
declare function f1(p: Point): void;
f1({
x: 10,
y: 20,
moveBy(dx, dy, dz) {
this.x += dx;
this.y += dy;
if (this.z && dz) {
this.z += dz;
}
}
});
// In methods of an object literal with a contextual type that includes some
// ThisType<T>, 'this' is of type T.
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
}
declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;
let x1 = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
// In methods contained in an object literal with a contextual type that includes
// some ThisType<T>, 'this' is of type T.
type ObjectDescriptor2<D, M> = ThisType<D & M> & {
data?: D;
methods?: M;
}
declare function makeObject2<D, M>(desc: ObjectDescriptor<D, M>): D & M;
let x2 = makeObject2({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
}
}
});
// Check pattern similar to Object.defineProperty and Object.defineProperties
type PropDesc<T> = {
value?: T;
get?(): T;
set?(value: T): void;
}
type PropDescMap<T> = {
[K in keyof T]: PropDesc<T[K]>;
}
declare function defineProp<T, K extends string, U>(obj: T, name: K, desc: PropDesc<U> & ThisType<T>): T & Record<K, U>;
declare function defineProps<T, U>(obj: T, descs: PropDescMap<U> & ThisType<T>): T & U;
let p10 = defineProp(p1, "foo", { value: 42 });
p10.foo = p10.foo + 1;
let p11 = defineProp(p1, "bar", {
get() {
return this.x;
},
set(value: number) {
this.x = value;
}
});
p11.bar = p11.bar + 1;
let p12 = defineProps(p1, {
foo: {
value: 42
},
bar: {
get(): number {
return this.x;
},
set(value: number) {
this.x = value;
}
}
});
p12.foo = p12.foo + 1;
p12.bar = p12.bar + 1;
// Proof of concept for typing of Vue.js
type Accessors<T> = { [K in keyof T]: (() => T[K]) | Computed<T[K]> };
type Dictionary<T> = { [x: string]: T }
type Computed<T> = {
get?(): T;
set?(value: T): void;
}
type VueOptions<D, M, P> = ThisType<D & M & P> & {
data?: D | (() => D);
methods?: M;
computed?: Accessors<P>;
}
declare const Vue: new <D, M, P>(options: VueOptions<D, M, P>) => D & M & P;
let vue = new Vue({
data: () => ({ x: 1, y: 2 }),
methods: {
f(x: string) {
return this.x;
}
},
computed: {
test(): number {
return this.x;
},
hello: {
get() {
return "hi";
},
set(value: string) {
}
}
}
});
vue;
vue.x;
vue.f("abc");
vue.test;
vue.hello;