mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Resolve more jsdoc value references as types (#34515)
* Resolve more jsdoc value references as types * add test
This commit is contained in:
parent
262ec6171d
commit
f5dbcb78af
@ -10740,7 +10740,7 @@ namespace ts {
|
||||
errorType;
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) {
|
||||
const jsdocType = getTypeFromJSAlias(node, symbol);
|
||||
const jsdocType = getTypeFromJSDocValueReference(node, symbol);
|
||||
if (jsdocType) {
|
||||
return jsdocType;
|
||||
}
|
||||
@ -10754,19 +10754,25 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* A JSdoc TypeReference may be to a value imported from commonjs.
|
||||
* These should really be aliases, but this special-case code fakes alias resolution
|
||||
* by producing a type from a value.
|
||||
* A JSdoc TypeReference may be to a value, but resolve it as a type anyway.
|
||||
* Note: If the value is imported from commonjs, it should really be an alias,
|
||||
* but this function fakes special-case code fakes alias resolution as well.
|
||||
*/
|
||||
function getTypeFromJSAlias(node: NodeWithTypeArguments, symbol: Symbol): Type | undefined {
|
||||
function getTypeFromJSDocValueReference(node: NodeWithTypeArguments, symbol: Symbol): Type | undefined {
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
const typeType =
|
||||
valueType.symbol &&
|
||||
valueType.symbol !== symbol && // Make sure this is a commonjs export by checking that symbol -> type -> symbol doesn't roundtrip.
|
||||
getTypeReferenceType(node, valueType.symbol);
|
||||
if (typeType) {
|
||||
return getSymbolLinks(symbol).resolvedJSDocType = typeType;
|
||||
let typeType = valueType;
|
||||
if (symbol.valueDeclaration) {
|
||||
const decl = getRootDeclaration(symbol.valueDeclaration);
|
||||
const isRequireAlias = isVariableDeclaration(decl)
|
||||
&& decl.initializer
|
||||
&& isCallExpression(decl.initializer)
|
||||
&& isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true)
|
||||
&& valueType.symbol;
|
||||
if (isRequireAlias) {
|
||||
typeType = getTypeReferenceType(node, valueType.symbol);
|
||||
}
|
||||
}
|
||||
return getSymbolLinks(symbol).resolvedJSDocType = typeType;
|
||||
}
|
||||
|
||||
function getSubstitutionType(typeVariable: TypeVariable, substitute: Type) {
|
||||
|
||||
@ -1819,9 +1819,9 @@ namespace ts {
|
||||
* exactly one argument (of the form 'require("name")').
|
||||
* This function does not test if the node is in a JavaScript file or not.
|
||||
*/
|
||||
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteralLike: true): callExpression is RequireOrImportCall & { expression: Identifier, arguments: [StringLiteralLike] };
|
||||
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteralLike: boolean): callExpression is CallExpression;
|
||||
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteralLike: boolean): callExpression is CallExpression {
|
||||
export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: true): callExpression is RequireOrImportCall & { expression: Identifier, arguments: [StringLiteralLike] };
|
||||
export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: boolean): callExpression is CallExpression;
|
||||
export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: boolean): callExpression is CallExpression {
|
||||
if (callExpression.kind !== SyntaxKind.CallExpression) {
|
||||
return false;
|
||||
}
|
||||
@ -1835,7 +1835,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
const arg = args[0];
|
||||
return !checkArgumentIsStringLiteralLike || isStringLiteralLike(arg);
|
||||
return !requireStringLiteralLikeArgument || isStringLiteralLike(arg);
|
||||
}
|
||||
|
||||
export function isSingleOrDoubleQuote(charCode: number) {
|
||||
|
||||
@ -5,7 +5,6 @@ tests/cases/compiler/index4.js(2,19): error TS2315: Type 'Function' is not gener
|
||||
tests/cases/compiler/index5.js(2,19): error TS2315: Type 'String' is not generic.
|
||||
tests/cases/compiler/index6.js(2,19): error TS2315: Type 'Number' is not generic.
|
||||
tests/cases/compiler/index7.js(2,19): error TS2315: Type 'Object' is not generic.
|
||||
tests/cases/compiler/index8.js(4,12): error TS2749: 'fn' refers to a value, but is being used as a type here.
|
||||
tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'.
|
||||
|
||||
|
||||
@ -84,13 +83,11 @@ tests/cases/compiler/index8.js(4,15): error TS2304: Cannot find name 'T'.
|
||||
return 'Hello ' + somebody;
|
||||
}
|
||||
|
||||
==== tests/cases/compiler/index8.js (2 errors) ====
|
||||
==== tests/cases/compiler/index8.js (1 errors) ====
|
||||
function fn() {}
|
||||
|
||||
/**
|
||||
* @param {fn<T>} somebody
|
||||
~~
|
||||
!!! error TS2749: 'fn' refers to a value, but is being used as a type here.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
*/
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
tests/cases/conformance/jsdoc/bug27342.js(3,11): error TS2709: Cannot use namespace 'exports' as a type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/bug27342.js (1 errors) ====
|
||||
module.exports = {}
|
||||
/**
|
||||
* @type {exports}
|
||||
~~~~~~~
|
||||
!!! error TS2709: Cannot use namespace 'exports' as a type.
|
||||
*/
|
||||
var x
|
||||
|
||||
|
||||
10
tests/baselines/reference/jsdocTypeReferenceToValue.symbols
Normal file
10
tests/baselines/reference/jsdocTypeReferenceToValue.symbols
Normal file
@ -0,0 +1,10 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/** @param {Image} image */
|
||||
function process(image) {
|
||||
>process : Symbol(process, Decl(foo.js, 0, 0))
|
||||
>image : Symbol(image, Decl(foo.js, 1, 17))
|
||||
|
||||
return new image(1, 1)
|
||||
>image : Symbol(image, Decl(foo.js, 1, 17))
|
||||
}
|
||||
|
||||
13
tests/baselines/reference/jsdocTypeReferenceToValue.types
Normal file
13
tests/baselines/reference/jsdocTypeReferenceToValue.types
Normal file
@ -0,0 +1,13 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/** @param {Image} image */
|
||||
function process(image) {
|
||||
>process : (image: new (width?: number, height?: number) => HTMLImageElement) => HTMLImageElement
|
||||
>image : new (width?: number, height?: number) => HTMLImageElement
|
||||
|
||||
return new image(1, 1)
|
||||
>new image(1, 1) : HTMLImageElement
|
||||
>image : new (width?: number, height?: number) => HTMLImageElement
|
||||
>1 : 1
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
// @Filename: foo.js
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
/** @param {Image} image */
|
||||
function process(image) {
|
||||
return new image(1, 1)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user