mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #14141 from Microsoft/contextualThisType
Typed 'this' in object literal methods
This commit is contained in:
+211
-154
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Vendored
+8
-3
@@ -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;
|
||||
|
||||
@@ -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
|
||||
>{} : {}
|
||||
>{} : {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// @noImplicitAny: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
interface MouseEvent {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// @noImplicitAny: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
class C {
|
||||
x: number;
|
||||
constructor() {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
Reference in New Issue
Block a user