Fixing Lodash TypeScript Errors By Upgrading @types/lodash In Node Or Webpack
CAUTION: This post is primarily for Google-love, to help anyone else who might run into the same issue find and fix particular error messages.
I love using Lodash. It's an amazing utility library that has a very flexible API. But, sometimes, I find myself implementing the same pattern over-and-over again. In such situations, I like to encapsulate that pattern in an easier-to-consume proxy method that invokes Lodash behind the scenes. Prior to using TypeScript, this was never much cause for concern. But, when I tried to use this same approach in my Incident Commander TypeScript project, I kept running into TypeScript errors. It turns out, the fix for this was to upgrade my Definitely Typed "@types/lodash" module.
To paint the picture, I had created a "lodash-extended" module in my TypeScript application:
// Import the core node services.
import find = require( "lodash/find" );
import random = require( "lodash/random" );
import range = require( "lodash/range" );
import without = require( "lodash/without" );
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
// I provide a convenience method for searching by "id".
function findByID<T>( collection: T[], id: any ) : T | undefined {
return( find( collection, [ "id", id ] ) );
}
// Package the individual lodash functions as a local / extended version of lodash.
// --
// NOTE: This exploration is geared towards applications that need to build a deliver
// a compiled file to the browser. If you're on the server only, this is much less of
// an issue.
export var _ = {
find,
findByID, // <---- Our convenience method.
random,
range,
without
};
In this module, I'm cherry-picking some of the Lodash functions that I want to include in my application. Not that it's entirely relevant to this post, but I was using this approach so that I could clearly see which Lodash functions would have to be reflected in my vendor file. In addition to the core Lodash methods, I'm also exporting a findByID() method that implements a pattern that I was using everywhere in my application.
My main file would then import this lodash-extended module and try to use it:
// Import the core node services.
import { _ } from "./lodash-extended";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var friends = [
{ id: 1, name: "Kim" },
{ id: 2, name: "Sarah" },
{ id: 3, name: "Joanna" }
];
// Find a friend using the native find() method and the "_.property" iteratee shorthand.
var friend1 = _.find( friends, [ "id", 1 ] );
// Find a friend using our convenience method that wraps the "_.property" usage.
var friend3 = _.findByID( friends, 3 );
console.log( friend1 );
console.log( friend3 );
As you can see, we're just creating a simple collection and then comparing the native Lodash _.find() functionality to the custom findByID() method.
When I went to run this TypeScript demo using ts-node for the first time, I had the following package.json dependencies:
"dependencies": {
"@types/lodash": "4.14.66",
"@types/node": "8.0.26",
"lodash": "4.17.4",
"ts-node": "3.3.0",
"typescript": "2.3.4"
}
And, running the code resulting in the following TypeScript error:
TSError: Unable to compile TypeScript
lodash-extended.ts (14,28): Argument of type 'any[]' is not assignable to parameter of type 'Partial<T>'. (2345)
As a first step towards remediation, I tried to upgrade TypeScript to version 2.5.2:
"dependencies": {
"@types/lodash": "4.14.66",
"@types/node": "8.0.26",
"lodash": "4.17.4",
"ts-node": "3.3.0",
"typescript": "2.5.2" // <---- Upgraded.
}
After upgrading, I was still getting a TypeScript error; but, it was slightly different:
TSError: Unable to compile TypeScript
test.ts (15,32): Type '(string | number)[]' has no properties in common with type 'Partial<{ id: number; name: string; }>'. (2559)
I then tried to upgrade my "@types/lodash" module to 4.14.74:
"dependencies": {
"@types/lodash": "4.14.74", // <---- Upgraded.
"@types/node": "8.0.26",
"lodash": "4.17.4",
"ts-node": "3.3.0",
"typescript": "2.3.4"
}
After upgrading "@types/lodash", running this application though ts-node finally worked:
So, I guess the moral of the story is that when you run into TypeScript errors that don't seem to make sense, try upgrading your TypeScript library and your type definitions. Hopefully this will help anyone else who may run into the same error messages.
Want to use code from this post? Check out the license.
Reader Comments
Somewhat related--given JetBrains' great TS support, I've started adding @types/lodash and other typing modules as devdependencies to my mom-TS projects. Increases bloat, sure--but provides great type inference! Perhaps installing these globally would work somehow...
Figured it out; I've published a package to help do this if anyone else is interested. https://npm.im/all-types :D
@Christopher,
I'm not too familiar with the IDEs (I just SublimeText which is basically a fancy text-editor). But, your approach sounds legit. Type definitions don't get compiled into the source, as I understand it; so, the final result shouldn't have any additional bloat.
I am facing this same exact issue on _.find function of lodash. I'm currently using Typescript 2.5.3 version as this is required by the Angular 5 Framework. There is no way that I can downgrade typescript version. Do you have a solution for this?
Any suggestions will help. At this point I'm ready to try anything to make it work.