32
loading...
This website collects cookies to deliver better user experience
.ts
extension instead of .js
. However, you can allow JavaScript files to be processed through the TypeScript compiler to avoid having to rewrite all your code in TypeScript.npm
:$ npm install typescript --save-dev
npx tsc
command. You can also install the compiler globally to make the tsc
command accessible from anywhere, but a local installation should be preferred so that builds are reproducible across different machines.tsconfig.json
file to manage the options for your project, such as the files to include and the types of checking you want to perform. Here's a minimal configuration that you can start with:{
"compilerOptions": {
"target": "es5",
"outDir": "dist"
"allowJs": true,
},
"include": ["./src/**/*"]
}
compilerOptions
and include
properties. The latter is used to specify an array of filenames or patterns to include in the program relative to the tsconfig.json
file. It supports wildcard characters to form glob patterns, which may or may not include a file extension. If the file extension is omitted (as above), only supported extensions are included: .ts
, .tsx
, .d.ts
by default, with .js
and .jsx
if compilerOptions.allowJs
is set to true
.compilerOptions
property, however, allows you to determine how loose or strict the compiler should be when processing the build. This is where the bulk of your configuration will be. Here's what each option specified above does:target
property above allows you to transform newer JavaScript syntax to an older version, such as ECMAScript 5.allowJs
causes the TypeScript compiler to accept JavaScript files (including imports). This is a way to incrementally convert to TypeScript by allowing .ts
and .tsx
files to live alongside existing JavaScript files.outDir
causes the build to be outputted to the dist
folder.npx tsc --watch
, and it will compile the source files and emit the output to the dist folder.npm
:$ npm install fork-ts-checker-webpack-plugin @babel/preset-typescript --save-dev
const path = require("path");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const typescript = {
test: /\.(ts|js)$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-typescript"],
},
},
],
};
module.exports = {
entry: {
main: "./src/main.ts",
},
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [typescript],
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js",
},
plugins: [new ForkTsCheckerWebpackPlugin()],
};
$ bundle exec rails webpacker:install:typescript
@babel/preset-typescript
package). You need to install the Fork TS Checker Webpack Plugin package manually if you want to enable type checking as part of the Webpack build process.$ yarn add --dev fork-ts-checker-webpack-plugin
config/webpack/development.js
file as shown below:const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const path = require("path");
environment.plugins.append(
"ForkTsCheckerWebpackPlugin",
new ForkTsCheckerWebpackPlugin({
typescript: {
configFile: path.resolve(__dirname, "../../tsconfig.json"),
},
async: false,
})
);
.ts
or .tsx
and fixing any type errors that the compiler emits. The main problem with this method is that you're likely to get hundreds or even thousands of errors (depending on the size of the project and strictness of your TypeScript configuration), and you'll have to put the development of new features on hold until you complete the migration, which may take an inordinate amount of time.allowJs
option), this process should be a breeze. All you need to do is add TypeScript to your build process and set up a basic configuration, such as the one presented earlier in this article. Afterwards, you need to ensure that any new features are implemented in TypeScript while existing code is moved over in an incremental manner.include
or files
property in your tsconfig.json
file, the compiler will start type checking any TypeScript files in your codebase. You can also enable type checking for JavaScript files through the checkJs
compiler option. This allows you to add type annotations to your JavaScript files using JSDoc so you can start to get a feel using types in your application but without fully committing to TypeScript..js
or .jsx
file to .ts
or .tsx
, respectively, and start using TypeScript syntax to define the types instead of JSDoc. For example, let's say that you have an add.js
file with the following code:// add.js
function add(x, y) {
return x + y;
}
export default add;
any
. This means that TypeScript won't perform any type checking for these values. You can opt into type checking the plain JavaScript file using JSDoc comments as shown below:// add.js
/**
* @param {number} x
* @param {number} y
* @returns {number}
*/
function add(x, y) {
return x + y;
}
export default add;
add
is used incorrectly, such as when a string is passed as an argument instead of a number..ts
and translate the JSDoc comments to the TypeScript syntax.// add.ts
function add(x: number, y: number): number {
return x + y;
}
export default add;
any
type to the entire library. This is problematic because you don't get any type safety with the any
type, so even if you use a method that does not exist, the compiler wont complain.import * as lodash from "lodash";
// lodash.sneeze() is not a function
lodash.sneeze();
.d.ts
file in which you describe the type definitions for another file or package. For example, you can create a main.d.ts
file in your source folder with the following contents:declare module "lodash" {
function sneeze(): string;
}
sneeze
function that returns a string. If you run the build again, it compiles because TypeScript trusts that the type definitions in the declaration file is correct, and it has no way of checking if they are actually accurate. Of course, the code will throw a runtime error since the sneeze
method does not exist.npm
under the @types
scope. For example, the types for the lodash package can be added through the following command:$ npm install --save @types/lodash
@types
folder which contains all typings. After running the command above, you will find a lodash
folder inside @types
which contains several files with the type information for all the lodash methods. The typescript compiler understands this convention so it will recognize the types automatically without your intervention.main.d.ts
and build the project once again. As you can see from the image above, it correctly reports that sneeze
does not exist. If we use a correct method like ceil
with the correct arguments, it compiles just fine. Also, you'll get that sweet autocompletion goodness with type annotations in your editor.interface Person {
name: string;
}
interface Person {
name: boolean;
age: number;
}
const jack: Person = {
name: "Jack",
age: 20,
};
console.log(jack);
Person
declarations are merged into one definition, so the jack
object contains the all the properties from both interfaces. One thing to note here is that subsequent property declarations of the same name must have the same type.interface Person {
name: string;
}
interface Person {
name: string; // works fine
age: number;
}
interface Person {
name: boolean; // throws an error
age: number;
}
sneeze
method really exists in lodash but is currently missing in the @types/lodash
package. You can add it through declaration merging in a .d.ts
file:// main.d.ts
import * as _ from "lodash";
declare module "lodash" {
interface LoDashStatic {
sneeze(): string;
}
}
declare module
to get inside the module. If you look at the @types/lodash package, you'll notice that all the methods are defined on the LoDashStatic
interface. To add a new method, all you need to do declare the interface again in the lodash
module and add the type definition for the function. At this point, if you try to use the sneeze
method in your code, it will compile along with all the other methods that exist on the original LoDashStatic
interface.@types
package is updated and published, you can remove the custom definition in the .d.ts
file and update the package through npm
, and everything else should keep working.