Does something look odd about this unit test? it('should square 4', () => {square(4);}); Sure. It doesn’t matter whether is implemented correctly. So long as the function doesn't throw an exception, this test will pass. It’s not asserting anything! square This isn’t great. The test would be much better if it checked the return value of : square(4) it('should square 4' () => {expect(square(4)).to.equal(16);}); Crazy as the first example is, it’s exactly how the type declarations in have traditionally been tested. It didn’t matter what the types were, so long as the type checker didn’t find any errors. Particularly in the presence of , this makes for some weak tests. Weak tests lead to imprecise and inaccurate typings, and they make refactoring type declarations scary. DefinitelyTyped [any](https://www.typescriptlang.org/docs/handbook/basic-types.html#any) types Microsoft recently introduced a new tool, , which makes assertions in type declaration tests possible. The rest of this post explains how to use it to bring all the benefits of testing to type declaration files. dtslint A test without dtslint Here are a few lines from the for , which I've : underscore tests _.pluck written about before Note the lack of assertions on the return type. What this is really checking is that there is a function named and that it accepts a list and a string as parameters. _.pluck The return type should be , but it's . Too bad! How can we make the test fail? string[] any[] A test to the rescue! To check the return type of the call to , we can use an assertion: dtslint _.pluck // $ExpectType When we run on this test it passes. But when we run on it we get the following: tsc dtslint ERROR: 2:1 expect Expected type to be: string[]got: any[] Tada! Caught! We can make the declaration precise : using a mapped type Now we get the following output from : dtslint Test with 2.8Test with 2.7Test with 2.6Test with 2.5Test with 2.4Test with 2.3Test with 2.2Test with 2.1Test with 2.0Error: /Users/danvk/github/dtslint-post/types/index.d.ts:1:33ERROR: 1:33 expect Compile error in typescript@2.0 but not in typescript@2.1.Fix with a comment '// TypeScript Version: 2.1' just under the header.Cannot find name 'keyof'. The tests pass with TypeScript 2.1+, but not with TypeScript 2.0. This make sense since was . Before TS 2.1, it wasn't possible to type this precisely. So our only real option is to require a newer version using the suggested comment: keyof introduced in TypeScript 2.1 pluck This gets at another reason that type declarations are hard to maintain. There are actually independent versions involved in type declarations: three The version of the library The version of the typings The version of the TypeScript compiler FlowTyped chooses to , whereas DefinitelyTyped does not. explicitly model this Refactoring with tests Suppose we’re working with type declarations for : lodash’s [map](https://lodash.com/docs#map) function export function map<U, V>(array: U[], fn: (u: U) => V): V[]; You use this much like : Array.prototype.map _.map([1, 2, 3], x => x * x); // returns [1, 4, 9]. Lodash has no function. Instead, it adds a variant of : _.pluck _.map We’d to model this in the type declarations, but it’s scary to alter the type of such an important function! This is one of the very best reasons to write tests: they let you refactor with confidence. lets you do the same with type declarations. dtslint Here’s a dtslint test for that covers both the old and new declarations: _.map Now we can add an overload to the declaration for : map When passes, we can be confident that we've both added the new functionality avoided changing existing behavior. dtslint and Testing callback parameters Callbacks are pervasive in and it’s important that type declarations accurately model their parameters. can help here, too: if we're careful about formatting, we can make assertions about the types of callback parameters. JavaScript dtslint actually passes three parameters to its callback. This snippet tests that all of them have the correct types inferred: _.map If we change any of those lines, we'll get an error. (This is often a good sanity check!) $ExpectType Testing the type of “this” It’s to know what refers to in JavaScript. But can help! If a library manipulates in its callbacks, then the type declarations should model that. famously hard this TypeScript this If you’ve made it this far, you won’t be surprised to find out that can help here, too! Just write a type assertion for : dtslint this Conclusion Dealing with inaccurate or imprecise type declarations can be one of the most frustrating aspects of working in TypeScript. They can introduce false errors or give you an unwarranted sense of confidence by introducing types where you weren't expecting them. any Testing is the key to improving an existing code base, and brings many of these benefits to TypeScript's type language. It lets you pin down existing behavior so that you can refactor type declarations with confidence. It even lets you do with type declaration files! dtslint test-driven development is already in use in the repo today. So if you're writing type declarations, please write some type assertions! And if you're changing existing type declarations, please write assertions for the existing behavior. dtslint DefinitelyTyped It's my hope that, over the long run, will lead to dramatically higher quality type declarations for all TypeScript users. And that means a better TypeScript experience, even if you don't know that exists! dtslint dtslint Check out this repo to see all the code samples from this post in action. If you’d like to use dtslint outside of DefinitelyTyped, check out Paul Körbitz’s great post .