Based on the TypeScript documentation on the lib
compiler option, is it redundant to set lib
compiler option to both dom
and dom.iterable
in TypeScript config file tsconfig.json
?
tsconfig.json
{
"compilerOptions": {
"lib": ["dom", "dom.iterable"],
}
}
I personally find the above setting to be redundant, but I have seen many sample codes/blog posts using the above option. But since I'm not sure, I want to know why the above settings would be used over the following:
{
"compilerOptions": {
"lib": ["dom"],
}
}
Maybe I'm just being nitpicky... Or maybe there is a valid reason unknown to me why one would specify both dom
and dom.iterable
. Any clarifications would be appreciated. Cheers!
CodePudding user response:
tl;dr: No, specifying both is not redundant.
dom.iterable
adds definitions for iterables to various DOM APIs. You would include dom
definitions if you're working with a runtime environment with DOM APIs. And you'd include dom.iterable
if you are working with a runtime environment that support iterable methods on various DOM APIs. Including dom
by itself when you're working with a runtime environment that support iterable methods on the DOM APIs that have them will mean you'll get type errors when attempting to access those iterable methods. Including dom.iterable
by itself won't work as it adds to the dom
definitions.
An example of differences
Here's an example of just one difference between the two definitions:
In the dom
definitions, FormData
looks like this:
interface FormData {
append(name: string, value: string | Blob, fileName?: string): void;
delete(name: string): void;
get(name: string): FormDataEntryValue | null;
getAll(name: string): FormDataEntryValue[];
has(name: string): boolean;
set(name: string, value: string | Blob, fileName?: string): void;
forEach(callbackfn: (value: FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
}
In the dom.iterable
definitions, FormData
looks like this:
interface FormData {
[Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
/**
* Returns an array of key, value pairs for every entry in the list.
*/
entries(): IterableIterator<[string, FormDataEntryValue]>;
/**
* Returns a list of keys in the list.
*/
keys(): IterableIterator<string>;
/**
* Returns a list of values in the list.
*/
values(): IterableIterator<FormDataEntryValue>;
}
The definitions don't replace each other but are merged.
Below are the definition files for your own comparison:
A practical test
Knowing the differences above you can do the following test:
- Setup a TypeScript project with the following config (the important bit is the empty array config for
lib
, everything else is just the defaults fromtsc --init
):
{
"compilerOptions": {
"lib": [],
"target": "es5",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
- Create an
index.ts
with the following contents:
const data = new FormData();
You should get an error from TypeScript:
Cannot find name 'FormData'.
- Add
"DOM"
to the lib configuration:
"compilerOptions": {
"lib": ["DOM"],
...
}
This resolves the error as FormData
is declared in the definitions for dom
.
- Add a call to the
keys
method fromFormData
, yourindex.ts
should look like this:
const data = new FormData();
data.keys();
You should get an error from TypeScript:
Property 'keys' does not exist on type 'FormData'.
- Add
"DOM.Iterable"
to the lib configuration:
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable"],
...
}
This resolves the error as the definitions for dom.iterable
declares some iterable methods for FormData
, keys
being one of them.
- Remove
"DOM"
from the lib configuration, leaving just"DOM.Iterable"
:
"compilerOptions": {
"lib": ["DOM.Iterable"],
...
}
You'll get an error again.