Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot read properties of undefined (reading '0') - weird errors #1427

Closed
rubiesonthesky opened this issue Mar 14, 2024 · 4 comments · Fixed by #1495
Closed

TypeError: Cannot read properties of undefined (reading '0') - weird errors #1427

rubiesonthesky opened this issue Mar 14, 2024 · 4 comments · Fixed by #1495
Labels
area: fixers Around how TypeStat fixes code. status: accepting prs Please, send a pull request to resolve this! 🙏 type: bug Something isn't working :( 🐛

Comments

@rubiesonthesky
Copy link
Collaborator

🐛 Bug Report

  • TypeStat version: 0.7.2
  • TypeScript version: 4.9.5
  • Node version: 20.10.0

Actual Behavior

There are a lot errors like this when I try to run the tool

Error in <project_path>/<path>/<file>.ts at node 'export interface ApiResponse {
  deleted: number;
  errors: string[];
}' (position 1652):
	TypeError: Cannot read properties of undefined (reading '0')
	    at Object.expandReferencesForGenericTypes (<project_path>/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/collectGenericNodeReferences.js:79:77)
	    at Object.collectGenericNodeReferences (<project_path>/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/collectGenericNodeReferences.js:35:20)
	    at visitInterfaceOrTypeLiteral (<project_path>/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/index.js:35:66)
	    at tryGetMutation (<project_path>/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:46:16)
	    at visitNode (<project_path>/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:33:30)
	    at visitNodes (<project_path>/node_modules/typescript/lib/typescript.js:31216:30)
	    at forEachChildInSourceFile (<project_path>/node_modules/typescript/lib/typescript.js:31575:20)
	    at Object.forEachChild (<project_path>/node_modules/typescript/lib/typescript.js:31990:47)
	    at Object.collectMutationsFromNodes (<project_path>/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:40:8)
	    at fixIncompleteInterfaceOrTypeLiteralGenerics (<project_path>/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/index.js:30:94)

Also, some places imports are overwritten like this. Not sure if these are connected. They do not seem to, but you never know.

-import {SearchApiService} from '../services/search-api.service';
+import {SearchApiService} from '../service | List<T>s/search-api.service';

Expected Behavior

Not throw weirds errors without explanation.

Reproduction

I have been trying with few different setups, but here is latest

{
  "include": [
    "src/**/*.ts"
  ],
  "filters": [
    "CallExpression[expression.text=suiteTeardown]",
    "CallExpression[expression.text=teardown]",
    "MethodDeclaration[name.text=dispose]"
  ],
  "fixes": {
    "incompleteTypes": true
  },
  "types": {
    "matching": [
      "^(null|undefined)$"
    ],
    "onlyPrimitives": true,
    "strictNullChecks": true
  }
}

Unfortunately, this is not a repo I can share straight away. It's Angular project, so there are legacy/experimental decorators for example. Strict options look like this

    "experimentalDecorators": true,
    "alwaysStrict": true,
    "noImplicitAny": false,
    "noImplicitOverride": false,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strictNullChecks": false,
    "strictPropertyInitialization": false,
    "useUnknownInCatchVariables": true

I think this code that the error points to this.

        // Find the index of the corresponding type argument in the instantation of the node,
        // and finally use that to grab the node for the template parameter from the type argument's index
        const typeArgumentIndex = templatedParentInstantiation.typeArguments.indexOf(referencingNode);
        const templateDeclaredTypeNode = templatedDeclaration.typeParameters[typeArgumentIndex];

I have tried to restrict to run only on some files, and I suspect that Angular decorators are one culprit here.

@JoshuaKGoldberg
Copy link
Owner

Thanks for posting! I tried playing a bit with experimental decorators locally but couldn't figure out how to reproduce this error. 😕

@rubiesonthesky I'd be happy to sign an NDA and take a look at the code privately. Otherwise, without a reproduction, I'm stuck here.

@JoshuaKGoldberg JoshuaKGoldberg added the status: needs reproduction The issue was filed with a missing or incomplete reproduction, and it can't be reproduced locally. label Mar 23, 2024
@rubiesonthesky
Copy link
Collaborator Author

I think, version 0.7.3 fixed the problem where with messing up imports.

I'm still getting a lot errors in the console though with same message TypeError: Cannot read properties of undefined (reading '0'). But I feel we are getting closer to the problem.

@rubiesonthesky
Copy link
Collaborator Author

I found a way to reproduce this! :D

Use typestat in this repo with npx -g typestat and with typestat.json

{
    "fixes": {
        "incompleteTypes": true
    },
    "include": [
        "src/**/*.{ts,tsx}"
    ],
    "projectPath": "tsconfig.json"
}

Error

Error in //TypeStat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteReactTypes/fixReactPropFunctionsFromCalls/createFunctionCallTypesMutation.ts at node 'interface CombinedFunctionType {
        parameters: ts.Type[][];
        returnValue?: ts.Type[];
}' (position 413):
        TypeError: Cannot read properties of undefined (reading '0')
            at expandReferencesForGenericTypes (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/collectGenericNodeReferences.js:83:77)
            at collectGenericNodeReferences (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/collectGenericNodeReferences.js:39:56)
            at visitInterfaceOrTypeLiteral (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/index.js:39:99)
            at tryGetMutation (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:50:16)
            at visitNode (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:37:30)
            at visitNodes (/.npm/_npx/42ab35185b79194c/node_modules/typestat/node_modules/typescript/lib/typescript.js:28303:24)
            at forEachChildInSourceFile (/.npm/_npx/42ab35185b79194c/node_modules/typestat/node_modules/typescript/lib/typescript.js:28946:18)
            at Object.forEachChild (/.npm/_npx/42ab35185b79194c/node_modules/typestat/node_modules/typescript/lib/typescript.js:28388:37)
            at collectMutationsFromNodes (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/collectMutationsFromNodes.js:44:8)
            at fixIncompleteInterfaceOrTypeLiteralGenerics (/.npm/_npx/42ab35185b79194c/node_modules/typestat/src/mutators/builtIn/fixIncompleteTypes/fixIncompleteInterfaceOrTypeLiteralGenerics/index.js:34:124)

@JoshuaKGoldberg JoshuaKGoldberg added type: bug Something isn't working :( 🐛 status: accepting prs Please, send a pull request to resolve this! 🙏 area: fixers Around how TypeStat fixes code. and removed status: needs reproduction The issue was filed with a missing or incomplete reproduction, and it can't be reproduced locally. labels Mar 30, 2024
@rubiesonthesky
Copy link
Collaborator Author

I'm seeing this also in mutation tests.

original.ts:

import ts from "typescript";

(function () {
	interface FunctionCallType {
		parameters?: (ts.Type | undefined)[];
		returnValue?: ts.Type;
	}
	interface CombinedFunctionType {
		parameters: ts.Type[][];
		returnValue?: ts.Type[];
	}

	const functionCallTypes: FunctionCallType[] = [];
	const combinedType = functionCallTypes.reduce<CombinedFunctionType>(
		(accumulator, functionCallType) => {
			return {
				parameters: combineParameters(
					undefined,
					accumulator.parameters,
					functionCallType.parameters,
				),
				returnValue: collectOptionals(accumulator.returnValue, [
					functionCallType.returnValue,
				]).filter(isNotUndefined),
			};
		},
		{
			parameters: [],
			returnValue: [],
		},
	);

	const combineParameters = (
		request: unknown,
		previous: ts.Type[][],
		next: (ts.Type | undefined)[] | undefined,
	) => {
		if (next === undefined) {
			return previous;
		}

		const combined: ts.Type[][] = [];
		let i: number;

		for (i = 0; i < previous.length; i += 1) {
			combined.push([...previous[i]]);

			if (i < next.length && next[i] !== undefined) {
				// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
				combined[i].push(next[i]!);
			}
		}

		for (i; i < next.length; i += 1) {
			if (next[i] !== undefined) {
				// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
				combined.push([next[i]!]);
			}
		}

		return combined;
	};

	const collectOptionals = <T>(
		...arrays: (readonly T[] | undefined)[]
	): T[] => {
		const results: T[] = [];

		for (const array of arrays) {
			if (array !== undefined) {
				results.push(...array);
			}
		}

		return results;
	};

	const isNotUndefined = <T>(item: T | undefined): item is T =>
		item !== undefined;
})();

This could probably be simplified a lot from this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: fixers Around how TypeStat fixes code. status: accepting prs Please, send a pull request to resolve this! 🙏 type: bug Something isn't working :( 🐛
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants