Treat ...
in jsdoc type as creating a synthetic rest parameter -- not as an array type (#19483)
* Treat `...` in jsdoc type as creating a synthetic rest parameter -- not as an array type * Change type parsing so `...T[]` parses as `...(T[])` and not `(...T)[]` * Replace the last parameter with ...args, and make access to it potentially undefined * Code review
This commit is contained in:
parent
3d05952719
commit
4b96edf72f
|
@ -2924,32 +2924,24 @@ namespace ts {
|
|||
|
||||
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration {
|
||||
const parameterDeclaration = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
|
||||
if (isTransientSymbol(parameterSymbol) && parameterSymbol.isRestParameter) {
|
||||
// special-case synthetic rest parameters in JS files
|
||||
return createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
parameterSymbol.isRestParameter ? createToken(SyntaxKind.DotDotDotToken) : undefined,
|
||||
"args",
|
||||
/*questionToken*/ undefined,
|
||||
typeToTypeNodeHelper(anyArrayType, context),
|
||||
/*initializer*/ undefined);
|
||||
}
|
||||
const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone);
|
||||
const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined;
|
||||
const name = parameterDeclaration.name ?
|
||||
parameterDeclaration.name.kind === SyntaxKind.Identifier ?
|
||||
setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
|
||||
cloneBindingName(parameterDeclaration.name) :
|
||||
symbolName(parameterSymbol);
|
||||
const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||
Debug.assert(!!parameterDeclaration || isTransientSymbol(parameterSymbol) && !!parameterSymbol.isRestParameter);
|
||||
|
||||
let parameterType = getTypeOfSymbol(parameterSymbol);
|
||||
if (isRequiredInitializedParameter(parameterDeclaration)) {
|
||||
parameterType = getNullableType(parameterType, TypeFlags.Undefined);
|
||||
if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) {
|
||||
parameterType = getOptionalType(parameterType);
|
||||
}
|
||||
const parameterTypeNode = typeToTypeNodeHelper(parameterType, context);
|
||||
|
||||
const modifiers = parameterDeclaration && parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone);
|
||||
const dotDotDotToken = !parameterDeclaration || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined;
|
||||
const name = parameterDeclaration
|
||||
? parameterDeclaration.name ?
|
||||
parameterDeclaration.name.kind === SyntaxKind.Identifier ?
|
||||
setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
|
||||
cloneBindingName(parameterDeclaration.name) :
|
||||
symbolName(parameterSymbol)
|
||||
: symbolName(parameterSymbol);
|
||||
const questionToken = parameterDeclaration && isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||
const parameterNode = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
|
@ -3717,7 +3709,7 @@ namespace ts {
|
|||
|
||||
let type = getTypeOfSymbol(p);
|
||||
if (parameterNode && isRequiredInitializedParameter(parameterNode)) {
|
||||
type = getNullableType(type, TypeFlags.Undefined);
|
||||
type = getOptionalType(type);
|
||||
}
|
||||
buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
@ -4288,8 +4280,8 @@ namespace ts {
|
|||
return expr.kind === SyntaxKind.ArrayLiteralExpression && (<ArrayLiteralExpression>expr).elements.length === 0;
|
||||
}
|
||||
|
||||
function addOptionality(type: Type, optional: boolean): Type {
|
||||
return strictNullChecks && optional ? getNullableType(type, TypeFlags.Undefined) : type;
|
||||
function addOptionality(type: Type, optional = true): Type {
|
||||
return strictNullChecks && optional ? getOptionalType(type) : type;
|
||||
}
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
|
@ -4318,7 +4310,7 @@ namespace ts {
|
|||
const typeNode = getEffectiveTypeAnnotationNode(declaration);
|
||||
if (typeNode) {
|
||||
const declaredType = getTypeFromTypeNode(typeNode);
|
||||
return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
return addOptionality(declaredType, /*optional*/ !!declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
if ((noImplicitAny || isInJavaScriptFile(declaration)) &&
|
||||
|
@ -4362,14 +4354,14 @@ namespace ts {
|
|||
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
}
|
||||
if (type) {
|
||||
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
return addOptionality(type, /*optional*/ !!declaration.questionToken && includeOptionality);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
const type = checkDeclarationInitializer(declaration);
|
||||
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
return addOptionality(type, /*optional*/ !!declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
if (isJsxAttribute(declaration)) {
|
||||
|
@ -4707,7 +4699,7 @@ namespace ts {
|
|||
links.type = baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type;
|
||||
}
|
||||
else {
|
||||
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? getNullableType(type, TypeFlags.Undefined) : type;
|
||||
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type) : type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6505,21 +6497,35 @@ namespace ts {
|
|||
const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ?
|
||||
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
|
||||
undefined;
|
||||
// JS functions get a free rest parameter if they reference `arguments`
|
||||
let hasRestLikeParameter = hasRestParameter(declaration);
|
||||
if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && containsArgumentsReference(declaration)) {
|
||||
hasRestLikeParameter = true;
|
||||
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String);
|
||||
syntheticArgsSymbol.type = anyArrayType;
|
||||
syntheticArgsSymbol.isRestParameter = true;
|
||||
parameters.push(syntheticArgsSymbol);
|
||||
}
|
||||
|
||||
const hasRestLikeParameter = hasRestParameter(declaration) || isInJavaScriptFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters);
|
||||
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestLikeParameter, hasLiteralTypes);
|
||||
}
|
||||
return links.resolvedSignature;
|
||||
}
|
||||
|
||||
function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration, parameters: Symbol[]): boolean {
|
||||
// JS functions get a free rest parameter if:
|
||||
// a) The last parameter has `...` preceding its type
|
||||
// b) It references `arguments` somewhere
|
||||
const lastParam = lastOrUndefined(declaration.parameters);
|
||||
const lastParamTags = lastParam && getJSDocParameterTags(lastParam);
|
||||
const lastParamVariadicType = lastParamTags && firstDefined(lastParamTags, p =>
|
||||
p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined);
|
||||
if (!lastParamVariadicType && !containsArgumentsReference(declaration)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String);
|
||||
syntheticArgsSymbol.type = lastParamVariadicType ? createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)) : anyArrayType;
|
||||
syntheticArgsSymbol.isRestParameter = true;
|
||||
if (lastParamVariadicType) {
|
||||
// Replace the last parameter with a rest parameter.
|
||||
parameters.pop();
|
||||
}
|
||||
parameters.push(syntheticArgsSymbol);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, isJSConstructSignature: boolean, classType: Type) {
|
||||
if (isJSConstructSignature) {
|
||||
return getTypeFromTypeNode(declaration.parameters[0].type);
|
||||
|
@ -7074,7 +7080,7 @@ namespace ts {
|
|||
|
||||
function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) {
|
||||
const type = getTypeFromTypeNode(node.type);
|
||||
return strictNullChecks ? getUnionType([type, nullType]) : type;
|
||||
return strictNullChecks ? getNullableType(type, TypeFlags.Null) : type;
|
||||
}
|
||||
|
||||
function getTypeFromTypeReference(node: TypeReferenceType): Type {
|
||||
|
@ -8048,15 +8054,6 @@ namespace ts {
|
|||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const type = getTypeFromTypeNode(node.type);
|
||||
links.resolvedType = type ? createArrayType(type) : unknownType;
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getThisType(node: Node): Type {
|
||||
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
|
||||
const parent = container && container.parent;
|
||||
|
@ -8130,6 +8127,8 @@ namespace ts {
|
|||
case SyntaxKind.JSDocOptionalType:
|
||||
case SyntaxKind.JSDocTypeExpression:
|
||||
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression>node).type);
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return getTypeFromJSDocVariadicType(node as JSDocVariadicType);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
|
@ -8148,8 +8147,6 @@ namespace ts {
|
|||
case SyntaxKind.QualifiedName:
|
||||
const symbol = getSymbolAtLocation(node);
|
||||
return symbol && getDeclaredTypeOfSymbol(symbol);
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return getTypeFromJSDocVariadicType(<JSDocVariadicType>node);
|
||||
default:
|
||||
return unknownType;
|
||||
}
|
||||
|
@ -10416,6 +10413,11 @@ namespace ts {
|
|||
getUnionType([type, undefinedType, nullType]);
|
||||
}
|
||||
|
||||
function getOptionalType(type: Type): Type {
|
||||
Debug.assert(strictNullChecks);
|
||||
return type.flags & TypeFlags.Undefined ? type : getUnionType([type, undefinedType]);
|
||||
}
|
||||
|
||||
function getNonNullableType(type: Type): Type {
|
||||
return strictNullChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
|
||||
}
|
||||
|
@ -12765,7 +12767,7 @@ namespace ts {
|
|||
declaration.flags & NodeFlags.Ambient;
|
||||
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) :
|
||||
type === autoType || type === autoArrayType ? undefinedType :
|
||||
getNullableType(type, TypeFlags.Undefined);
|
||||
getOptionalType(type);
|
||||
const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized);
|
||||
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
|
||||
// from declaration to use, and when the variable's declared type doesn't include undefined but the
|
||||
|
@ -17211,7 +17213,7 @@ namespace ts {
|
|||
if (strictNullChecks) {
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && (<VariableLikeDeclaration>declaration).initializer) {
|
||||
return getNullableType(type, TypeFlags.Undefined);
|
||||
return getOptionalType(type);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
|
@ -23060,14 +23062,15 @@ namespace ts {
|
|||
case SyntaxKind.JSDocFunctionType:
|
||||
checkSignatureDeclaration(node as JSDocFunctionType);
|
||||
// falls through
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
case SyntaxKind.JSDocNonNullableType:
|
||||
case SyntaxKind.JSDocNullableType:
|
||||
case SyntaxKind.JSDocAllType:
|
||||
case SyntaxKind.JSDocUnknownType:
|
||||
if (!isInJavaScriptFile(node) && !isInJSDoc(node)) {
|
||||
grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
|
||||
}
|
||||
checkJSDocTypeIsInJsFile(node);
|
||||
forEachChild(node, checkSourceElement);
|
||||
return;
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
checkJSDocVariadicType(node as JSDocVariadicType);
|
||||
return;
|
||||
case SyntaxKind.JSDocTypeExpression:
|
||||
return checkSourceElement((node as JSDocTypeExpression).type);
|
||||
|
@ -23144,6 +23147,65 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkJSDocTypeIsInJsFile(node: Node): void {
|
||||
if (!isInJavaScriptFile(node)) {
|
||||
grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
|
||||
}
|
||||
}
|
||||
|
||||
function checkJSDocVariadicType(node: JSDocVariadicType): void {
|
||||
checkJSDocTypeIsInJsFile(node);
|
||||
checkSourceElement(node.type);
|
||||
|
||||
// Only legal location is in the *last* parameter tag.
|
||||
const { parent } = node;
|
||||
if (!isJSDocTypeExpression(parent)) {
|
||||
error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature);
|
||||
}
|
||||
|
||||
const paramTag = parent.parent;
|
||||
if (!isJSDocParameterTag(paramTag)) {
|
||||
error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature);
|
||||
return;
|
||||
}
|
||||
|
||||
const param = getParameterSymbolFromJSDoc(paramTag);
|
||||
if (!param) {
|
||||
// We will error in `checkJSDocParameterTag`.
|
||||
return;
|
||||
}
|
||||
|
||||
const host = getHostSignatureFromJSDoc(paramTag);
|
||||
if (!host || last(host.parameters).symbol !== param) {
|
||||
error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type {
|
||||
const type = getTypeFromTypeNode(node.type);
|
||||
const { parent } = node;
|
||||
const paramTag = parent.parent;
|
||||
if (isJSDocTypeExpression(parent) && isJSDocParameterTag(paramTag)) {
|
||||
// Else we will add a diagnostic, see `checkJSDocVariadicType`.
|
||||
const param = getParameterSymbolFromJSDoc(paramTag);
|
||||
if (param) {
|
||||
const host = getHostSignatureFromJSDoc(paramTag);
|
||||
/*
|
||||
Only return an array type if the corresponding parameter is marked as a rest parameter.
|
||||
So in the following situation we will not create an array type:
|
||||
/** @param {...number} a * /
|
||||
function f(a) {}
|
||||
Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type.
|
||||
*/
|
||||
const lastParamDeclaration = host && last(host.parameters);
|
||||
if (lastParamDeclaration.symbol === param && isRestParameter(lastParamDeclaration)) {
|
||||
return createArrayType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return addOptionality(type);
|
||||
}
|
||||
|
||||
// Function and class expression bodies are checked after all statements in the enclosing body. This is
|
||||
// to ensure constructs like the following are permitted:
|
||||
// const foo = function () {
|
||||
|
@ -24272,7 +24334,7 @@ namespace ts {
|
|||
? getWidenedLiteralType(getTypeOfSymbol(symbol))
|
||||
: unknownType;
|
||||
if (flags & TypeFormatFlags.AddUndefined) {
|
||||
type = getNullableType(type, TypeFlags.Undefined);
|
||||
type = getOptionalType(type);
|
||||
}
|
||||
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
|
||||
}
|
||||
|
|
|
@ -3547,6 +3547,10 @@
|
|||
"category": "Error",
|
||||
"code": 8027
|
||||
},
|
||||
"JSDoc '...' may only appear in the last parameter of a signature.": {
|
||||
"category": "Error",
|
||||
"code": 8028
|
||||
},
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
|
|
|
@ -2678,8 +2678,6 @@ namespace ts {
|
|||
return parseJSDocUnknownOrNullableType();
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
return parseJSDocFunctionType();
|
||||
case SyntaxKind.DotDotDotToken:
|
||||
return parseJSDocNodeWithType(SyntaxKind.JSDocVariadicType);
|
||||
case SyntaxKind.ExclamationToken:
|
||||
return parseJSDocNodeWithType(SyntaxKind.JSDocNonNullableType);
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
|
@ -2819,6 +2817,12 @@ namespace ts {
|
|||
switch (token()) {
|
||||
case SyntaxKind.KeyOfKeyword:
|
||||
return parseTypeOperator(SyntaxKind.KeyOfKeyword);
|
||||
case SyntaxKind.DotDotDotToken: {
|
||||
const result = createNode(SyntaxKind.JSDocVariadicType) as JSDocVariadicType;
|
||||
nextToken();
|
||||
result.type = parsePostfixTypeOrHigher();
|
||||
return finishNode(result);
|
||||
}
|
||||
}
|
||||
return parsePostfixTypeOrHigher();
|
||||
}
|
||||
|
|
|
@ -1626,16 +1626,22 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
const name = node.name.escapedText;
|
||||
const decl = getHostSignatureFromJSDoc(node);
|
||||
if (!decl) {
|
||||
return undefined;
|
||||
}
|
||||
const parameter = find(decl.parameters, p => p.name.kind === SyntaxKind.Identifier && p.name.escapedText === name);
|
||||
return parameter && parameter.symbol;
|
||||
}
|
||||
|
||||
export function getHostSignatureFromJSDoc(node: JSDocParameterTag): FunctionLike | undefined {
|
||||
const host = getJSDocHost(node);
|
||||
const decl = getSourceOfAssignment(host) ||
|
||||
getSingleInitializerOfVariableStatement(host) ||
|
||||
getSingleVariableOfVariableStatement(host) ||
|
||||
getNestedModuleDeclaration(host) ||
|
||||
host;
|
||||
if (decl && isFunctionLike(decl)) {
|
||||
const parameter = find(decl.parameters, p => p.name.kind === SyntaxKind.Identifier && p.name.escapedText === name);
|
||||
return parameter && parameter.symbol;
|
||||
}
|
||||
return decl && isFunctionLike(decl) ? decl : undefined;
|
||||
}
|
||||
|
||||
export function getJSDocHost(node: JSDocTag): HasJSDoc {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* @param {...*} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
function apply(func, thisArg, ...args) {
|
||||
var length = args.length;
|
||||
switch (length) {
|
||||
case 0: return func.call(thisArg);
|
||||
|
@ -36,7 +36,11 @@ define("_apply", ["require", "exports"], function (require, exports) {
|
|||
* @param {...*} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
function apply(func, thisArg) {
|
||||
var args = [];
|
||||
for (var _i = 2; _i < arguments.length; _i++) {
|
||||
args[_i - 2] = arguments[_i];
|
||||
}
|
||||
var length = args.length;
|
||||
switch (length) {
|
||||
case 0: return func.call(thisArg);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* @param {...*} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
function apply(func, thisArg, ...args) {
|
||||
>apply : Symbol(apply, Decl(_apply.js, 0, 0))
|
||||
>func : Symbol(func, Decl(_apply.js, 10, 15))
|
||||
>thisArg : Symbol(thisArg, Decl(_apply.js, 10, 20))
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
* @param {...*} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
>apply : (func: Function, thisArg: any, args: any[]) => any
|
||||
function apply(func, thisArg, ...args) {
|
||||
>apply : (func: Function, thisArg: any, ...args: any[]) => any
|
||||
>func : Function
|
||||
>thisArg : any
|
||||
>args : any[]
|
||||
|
@ -84,5 +84,5 @@ function apply(func, thisArg, args) {
|
|||
}
|
||||
|
||||
export default apply;
|
||||
>apply : (func: Function, thisArg: any, args: any[]) => any
|
||||
>apply : (func: Function, thisArg: any, ...args: any[]) => any
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(11,12): error TS255
|
|||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(13,14): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(14,11): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(15,8): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(16,5): error TS2322: Type 'boolean[]' is not assignable to type 'boolean | undefined'.
|
||||
Type 'boolean[]' is not assignable to type 'false'.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(16,15): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(16,15): error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(17,11): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(18,17): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(19,5): error TS2322: Type 'undefined' is not assignable to type 'number | null'.
|
||||
|
@ -16,9 +19,10 @@ tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(21,16): error TS802
|
|||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(22,16): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(23,17): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(24,17): error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(24,17): error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts (18 errors) ====
|
||||
==== tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts (21 errors) ====
|
||||
// grammar error from checker
|
||||
var ara: Array.<number> = [1,2,3];
|
||||
~
|
||||
|
@ -53,8 +57,13 @@ tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(24,17): error TS802
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
var variadic: ...boolean = [true, false, true];
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type 'boolean[]' is not assignable to type 'boolean | undefined'.
|
||||
!!! error TS2322: Type 'boolean[]' is not assignable to type 'false'.
|
||||
~~~~~~~~~~
|
||||
!!! error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
~~~~~~~~~~
|
||||
!!! error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
var most: !string = 'definite';
|
||||
~~~~~~~
|
||||
!!! error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
|
@ -79,5 +88,7 @@ tests/cases/conformance/jsdoc/jsdocDisallowedInTypescript.ts(24,17): error TS802
|
|||
var vars: Array<...number>;
|
||||
~~~~~~~~~
|
||||
!!! error TS8020: JSDoc types can only be used inside documentation comments.
|
||||
~~~~~~~~~
|
||||
!!! error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ var g: function(number, number): number = (n,m) => n + m;
|
|||
>m : number
|
||||
|
||||
var variadic: ...boolean = [true, false, true];
|
||||
>variadic : boolean[]
|
||||
>variadic : boolean | undefined
|
||||
>[true, false, true] : boolean[]
|
||||
>true : true
|
||||
>false : false
|
||||
|
@ -96,7 +96,7 @@ var anys: Array<*>;
|
|||
>Array : T[]
|
||||
|
||||
var vars: Array<...number>;
|
||||
>vars : number[][]
|
||||
>vars : (number | undefined)[]
|
||||
>Array : T[]
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
tests/cases/conformance/jsdoc/prefixPostfix.js(8,13): error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(9,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(10,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(11,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(12,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(13,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
tests/cases/conformance/jsdoc/prefixPostfix.js(14,12): error TS1014: A rest parameter must be last in a parameter list.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/prefixPostfix.js (7 errors) ====
|
||||
/**
|
||||
* @param {number![]} x - number[]
|
||||
* @param {!number[]} y - number[]
|
||||
* @param {(number[])!} z - number[]
|
||||
* @param {number?[]} a - (number | null)[]
|
||||
* @param {?number[]} b - number[] | null
|
||||
* @param {(number[])?} c - number[] | null
|
||||
* @param {?...number} d - number[] | null
|
||||
~~~~~~~~~
|
||||
!!! error TS8028: JSDoc '...' may only appear in the last parameter of a signature.
|
||||
* @param {...?number} e - (number | null)[]
|
||||
~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number?} f - number[] | null
|
||||
~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number!?} g - number[] | null
|
||||
~~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number?!} h - number[] | null
|
||||
~~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number[]} i - number[][]
|
||||
~~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number![]?} j - number[][] | null
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS1014: A rest parameter must be last in a parameter list.
|
||||
* @param {...number?[]!} k - (number[] | null)[]
|
||||
*/
|
||||
function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) {
|
||||
}
|
||||
|
|
@ -16,20 +16,20 @@
|
|||
* @param {...number?[]!} k - (number[] | null)[]
|
||||
*/
|
||||
function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) {
|
||||
>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, e: (number | null)[], f: number[] | null, g: number[] | null, h: number[] | null, i: number[][], j: number[][] | null, k: (number[] | null)[]) => void
|
||||
>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number | null | undefined, e: number | null | undefined, f: number | null | undefined, g: number | null | undefined, h: number | null | undefined, i: number[] | undefined, j: number[] | null | undefined, ...args: (number | null)[][]) => void
|
||||
>x : number[]
|
||||
>y : number[]
|
||||
>z : number[]
|
||||
>a : (number | null)[]
|
||||
>b : number[] | null
|
||||
>c : number[] | null
|
||||
>d : number[] | null
|
||||
>e : (number | null)[]
|
||||
>f : number[] | null
|
||||
>g : number[] | null
|
||||
>h : number[] | null
|
||||
>i : number[][]
|
||||
>j : number[][] | null
|
||||
>k : (number[] | null)[]
|
||||
>d : number | null | undefined
|
||||
>e : number | null | undefined
|
||||
>f : number | null | undefined
|
||||
>g : number | null | undefined
|
||||
>h : number | null | undefined
|
||||
>i : number[] | undefined
|
||||
>j : number[] | null | undefined
|
||||
>k : (number | null)[] | undefined
|
||||
}
|
||||
|
||||
|
|
19
tests/baselines/reference/jsdocRestParameter.errors.txt
Normal file
19
tests/baselines/reference/jsdocRestParameter.errors.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
/a.js(7,3): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'number'.
|
||||
/a.js(8,6): error TS2345: Argument of type '"2"' is not assignable to parameter of type 'number'.
|
||||
|
||||
|
||||
==== /a.js (2 errors) ====
|
||||
/** @param {...number} a */
|
||||
function f(a) {
|
||||
a; // number | undefined
|
||||
// Ideally this would be a number. But currently checker.ts has only one `argumentsSymbol`, so it's `any`.
|
||||
arguments[0];
|
||||
}
|
||||
f([1, 2]); // Error
|
||||
~~~~~~
|
||||
!!! error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'number'.
|
||||
f(1, "2"); // Error
|
||||
~~~
|
||||
!!! error TS2345: Argument of type '"2"' is not assignable to parameter of type 'number'.
|
||||
f(1, 2);
|
||||
|
22
tests/baselines/reference/jsdocRestParameter.symbols
Normal file
22
tests/baselines/reference/jsdocRestParameter.symbols
Normal file
|
@ -0,0 +1,22 @@
|
|||
=== /a.js ===
|
||||
/** @param {...number} a */
|
||||
function f(a) {
|
||||
>f : Symbol(f, Decl(a.js, 0, 0))
|
||||
>a : Symbol(a, Decl(a.js, 1, 11))
|
||||
|
||||
a; // number | undefined
|
||||
>a : Symbol(a, Decl(a.js, 1, 11))
|
||||
|
||||
// Ideally this would be a number. But currently checker.ts has only one `argumentsSymbol`, so it's `any`.
|
||||
arguments[0];
|
||||
>arguments : Symbol(arguments)
|
||||
}
|
||||
f([1, 2]); // Error
|
||||
>f : Symbol(f, Decl(a.js, 0, 0))
|
||||
|
||||
f(1, "2"); // Error
|
||||
>f : Symbol(f, Decl(a.js, 0, 0))
|
||||
|
||||
f(1, 2);
|
||||
>f : Symbol(f, Decl(a.js, 0, 0))
|
||||
|
34
tests/baselines/reference/jsdocRestParameter.types
Normal file
34
tests/baselines/reference/jsdocRestParameter.types
Normal file
|
@ -0,0 +1,34 @@
|
|||
=== /a.js ===
|
||||
/** @param {...number} a */
|
||||
function f(a) {
|
||||
>f : (...args: number[]) => void
|
||||
>a : number | undefined
|
||||
|
||||
a; // number | undefined
|
||||
>a : number | undefined
|
||||
|
||||
// Ideally this would be a number. But currently checker.ts has only one `argumentsSymbol`, so it's `any`.
|
||||
arguments[0];
|
||||
>arguments[0] : any
|
||||
>arguments : IArguments
|
||||
>0 : 0
|
||||
}
|
||||
f([1, 2]); // Error
|
||||
>f([1, 2]) : void
|
||||
>f : (...args: number[]) => void
|
||||
>[1, 2] : number[]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
|
||||
f(1, "2"); // Error
|
||||
>f(1, "2") : void
|
||||
>f : (...args: number[]) => void
|
||||
>1 : 1
|
||||
>"2" : "2"
|
||||
|
||||
f(1, 2);
|
||||
>f(1, 2) : void
|
||||
>f : (...args: number[]) => void
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
|
10
tests/baselines/reference/jsdocRestParameter_es6.symbols
Normal file
10
tests/baselines/reference/jsdocRestParameter_es6.symbols
Normal file
|
@ -0,0 +1,10 @@
|
|||
=== /a.js ===
|
||||
/** @param {...number} a */
|
||||
function f(...a) {
|
||||
>f : Symbol(f, Decl(a.js, 0, 0))
|
||||
>a : Symbol(a, Decl(a.js, 1, 11))
|
||||
|
||||
a; // number[]
|
||||
>a : Symbol(a, Decl(a.js, 1, 11))
|
||||
}
|
||||
|
10
tests/baselines/reference/jsdocRestParameter_es6.types
Normal file
10
tests/baselines/reference/jsdocRestParameter_es6.types
Normal file
|
@ -0,0 +1,10 @@
|
|||
=== /a.js ===
|
||||
/** @param {...number} a */
|
||||
function f(...a) {
|
||||
>f : (...a: number[]) => void
|
||||
>a : number[]
|
||||
|
||||
a; // number[]
|
||||
>a : number[]
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* @param {...*} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
function apply(func, thisArg, ...args) {
|
||||
var length = args.length;
|
||||
switch (length) {
|
||||
case 0: return func.call(thisArg);
|
||||
|
|
15
tests/cases/compiler/jsdocRestParameter.ts
Normal file
15
tests/cases/compiler/jsdocRestParameter.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// @Filename: /a.js
|
||||
/** @param {...number} a */
|
||||
function f(a) {
|
||||
a; // number | undefined
|
||||
// Ideally this would be a number. But currently checker.ts has only one `argumentsSymbol`, so it's `any`.
|
||||
arguments[0];
|
||||
}
|
||||
f([1, 2]); // Error
|
||||
f(1, "2"); // Error
|
||||
f(1, 2);
|
10
tests/cases/compiler/jsdocRestParameter_es6.ts
Normal file
10
tests/cases/compiler/jsdocRestParameter_es6.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// @Filename: /a.js
|
||||
/** @param {...number} a */
|
||||
function f(...a) {
|
||||
a; // number[]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
// @strict: true
|
||||
/// <reference path='fourslash.ts' />
|
||||
////type T = [|...number?|];
|
||||
|
||||
verify.codeFix({
|
||||
description: "Change '...number?' to 'number[] | null'.",
|
||||
errorCode: 8020,
|
||||
index: 0,
|
||||
newRangeContent: "number[] | null",
|
||||
});
|
|
@ -1,7 +0,0 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
//// var x: [|......number[][]|] = 12;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Change '......number[][]' to 'number[][][][]'.",
|
||||
newRangeContent: "number[][][][]",
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
///<reference path="fourslash.ts" />
|
||||
|
||||
// @allowNonTsExtensions: true
|
||||
// @Filename: Foo.js
|
||||
/////**
|
||||
//// * @param {...number} a
|
||||
//// */
|
||||
////function foo(a) {
|
||||
//// a./**/
|
||||
////}
|
||||
|
||||
goTo.marker();
|
||||
verify.completionListContains("concat", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
|
|
@ -1,13 +0,0 @@
|
|||
///<reference path="fourslash.ts" />
|
||||
|
||||
// @allowNonTsExtensions: true
|
||||
// @Filename: Foo.js
|
||||
/////**
|
||||
//// * @param {...number} a
|
||||
//// */
|
||||
////function foo(a) {
|
||||
//// a[0]./**/
|
||||
////}
|
||||
|
||||
goTo.marker();
|
||||
verify.completionListContains("toExponential", /*displayText:*/ undefined, /*documentation*/ undefined, "method");
|
Loading…
Reference in a new issue