Infer from parameters annotated using JSDoc (#55400)

This commit is contained in:
Mateusz Burzyński
2023-08-28 16:02:52 -07:00
committed by GitHub
parent 32ebbe05dc
commit 418494e4c4
4 changed files with 123 additions and 7 deletions
+5 -7
View File
@@ -35600,13 +35600,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
for (let i = 0; i < len; i++) {
const declaration = signature.parameters[i].valueDeclaration as ParameterDeclaration;
if (declaration.type) {
const typeNode = getEffectiveTypeAnnotationNode(declaration);
if (typeNode) {
const source = addOptionality(getTypeFromTypeNode(typeNode), /*isProperty*/ false, isOptionalDeclaration(declaration));
const target = getTypeAtPosition(context, i);
inferTypes(inferenceContext.inferences, source, target);
}
const typeNode = getEffectiveTypeAnnotationNode(declaration);
if (typeNode) {
const source = addOptionality(getTypeFromTypeNode(typeNode), /*isProperty*/ false, isOptionalDeclaration(declaration));
const target = getTypeAtPosition(context, i);
inferTypes(inferenceContext.inferences, source, target);
}
}
}
@@ -0,0 +1,41 @@
//// [tests/cases/compiler/contravariantOnlyInferenceFromAnnotatedFunctionJs.ts] ////
=== index.js ===
/**
* @typedef {{ [K in keyof B]: { fn: (a: A, b: B) => void; thing: B[K]; } }} Funcs
* @template A
* @template {Record<string, unknown>} B
*/
/**
* @template A
* @template {Record<string, unknown>} B
* @param {Funcs<A, B>} fns
* @returns {[A, B]}
*/
function foo(fns) {
>foo : Symbol(foo, Decl(index.js, 0, 0))
>fns : Symbol(fns, Decl(index.js, 12, 13))
return /** @type {any} */ (null);
}
const result = foo({
>result : Symbol(result, Decl(index.js, 16, 5))
>foo : Symbol(foo, Decl(index.js, 0, 0))
bar: {
>bar : Symbol(bar, Decl(index.js, 16, 20))
fn:
>fn : Symbol(fn, Decl(index.js, 17, 8))
/** @param {string} a */
(a) => {},
>a : Symbol(a, Decl(index.js, 20, 7))
thing: "asd",
>thing : Symbol(thing, Decl(index.js, 20, 16))
},
});
@@ -0,0 +1,47 @@
//// [tests/cases/compiler/contravariantOnlyInferenceFromAnnotatedFunctionJs.ts] ////
=== index.js ===
/**
* @typedef {{ [K in keyof B]: { fn: (a: A, b: B) => void; thing: B[K]; } }} Funcs
* @template A
* @template {Record<string, unknown>} B
*/
/**
* @template A
* @template {Record<string, unknown>} B
* @param {Funcs<A, B>} fns
* @returns {[A, B]}
*/
function foo(fns) {
>foo : <A, B extends Record<string, unknown>>(fns: Funcs<A, B>) => [A, B]
>fns : Funcs<A, B>
return /** @type {any} */ (null);
>(null) : any
}
const result = foo({
>result : [string, { bar: string; }]
>foo({ bar: { fn: /** @param {string} a */ (a) => {}, thing: "asd", },}) : [string, { bar: string; }]
>foo : <A, B extends Record<string, unknown>>(fns: Funcs<A, B>) => [A, B]
>{ bar: { fn: /** @param {string} a */ (a) => {}, thing: "asd", },} : { bar: { fn: (a: string) => void; thing: string; }; }
bar: {
>bar : { fn: (a: string) => void; thing: string; }
>{ fn: /** @param {string} a */ (a) => {}, thing: "asd", } : { fn: (a: string) => void; thing: string; }
fn:
>fn : (a: string) => void
/** @param {string} a */
(a) => {},
>(a) => {} : (a: string) => void
>a : string
thing: "asd",
>thing : string
>"asd" : "asd"
},
});
@@ -0,0 +1,30 @@
// @strict: true
// @checkJs: true
// @noEmit: true
// @filename: index.js
/**
* @typedef {{ [K in keyof B]: { fn: (a: A, b: B) => void; thing: B[K]; } }} Funcs
* @template A
* @template {Record<string, unknown>} B
*/
/**
* @template A
* @template {Record<string, unknown>} B
* @param {Funcs<A, B>} fns
* @returns {[A, B]}
*/
function foo(fns) {
return /** @type {any} */ (null);
}
const result = foo({
bar: {
fn:
/** @param {string} a */
(a) => {},
thing: "asd",
},
});