In this second post in our two-part series on TypeScript, we will discuss the various places that you can use TypeScript within the Salesforce ecosystem.
Now that you have a basic understanding of how TypeScript works, let’s see where and how you can use TypeScript with Salesforce.
Lightning Web Components
*.ts) present in an LWC bundle that’s deployed to the Salesforce Platform can not be processed by the LWC platform compiler.
However, you can take full advantage of VS Code’s TypeScript language service and use the lesser strict levels of TypeScript as described in the previous post. You can even leverage TypeScript declaration files to declare types that can be used across different components. Since the language service just provides static analysis, you needn’t worry about compiling or adding additional steps to your deployment.
To get started, you first need to specify the types using JSDoc constructs. Then, add the flag
As a best practice, enable type checking for all of your LWC components at once by adding the
checkJs flag to the
compilerOptions in the
jsconfig.json file present in your SFDX project’s
lwc folder. Also, make sure you add
ESNext as a
target in the compiler options (the default if unspecified is ES3). This will prevent errors from showing up on ES5+ features like get/set accessors.
checkJs flag added, you don’t need to add
//@ts-check to each file anymore. Instead, to skip type checking on specific files, add the
//@ts-nocheck flag at the beginning of those files.
When working with Salesforce data, you can define types for each object you work with. In case you are wondering about the object definitions in the
/lwc/sobjects/ folder, those are type declarations for individual fields you import via
@salesforce/schema/<objecname>.<fieldname>. These are automatically created by the Salesforce Extension Pack. While it defines the type of individual fields, it doesn’t hold the definition of the object itself.
So here is how you define an object type, for example, a Contact.
VS Code will pick this up, enforce types, and show suggestions automatically. In the below GIF, you can see that when you type a dot(
contacts, it shows array methods like
every, etc. since
contacts is an array. But when you type a dot(
contacts, it shows the properties of the Contact type that you defined earlier.
Types defined in one component can be imported inside another. Here is how a component
HelloBinding would import the type
Contact defined in the
To ensure that your custom type definitions are available across all your components without having to manually import them, you can create a TypeScript declaration file (
*.d.ts) in the root of your project, and declare types using either type aliases or interfaces. For example, you can create a file
mytypes.d.ts and create two types.
Next, you need to instruct TypeScript to also look at this file to find the type declarations. You can do this by adding the file’s location to the
include property of the
jsconfig.json file present in your SFDX project’s
You can now use these types in your LWC components using the JSDoc syntax, without having to import them.
The declaration file can be committed to your source control so that every developer on the project can use the same file.
.sfdx/typings folder in your SFDX project also contains pre-defined type declarations for built-in modules like Lightning Message Service and Lightning Data Service adapters. Since this folder’s location is also present in the
include property of the
jsconfig.json, you can use these pre-defined types in your components. For example, the result of a getRecord operation has a certain shape, i.e., has pre-defined properties that don’t change based on the object you are querying. You can use VS Code’s suggestions to infer and import such types.
If you want stricter type checking, or want to author your components using
.ts files, you need to first run the TypeScript compiler before deploying your components to the Salesforce Platform. One option is to create a
predeploy Salesforce CLI hook that runs the
Lightning Web Runtime
This creates a project that uses TypeScript files (
tsconfig.json file at the root of the project.
Below is an example of a simple TypeScript LWC component that uses standard types and custom interfaces. While Line 17 works correctly at runtime, TypeScript treats it as an error, since we are trying to set a property that isn’t valid for that type.
Even here, you can create your own type declaration files to support your implementation. As a best practice, create a
types folder in the root of your project, and place your
*.d.ts files in this folder.
Next, add the path of the
types folder to the
include property of
You can now use these custom types in your components.
TypeScript is one of the supported languages for creating Salesforce Functions — just pass
typescript to the
-l flag when running the
generate function command.
This command creates a TypeScript function that is structured exactly like a typical TypeScript project with files like
A TypeScript function additionally includes the Salesforce Function SDK for Node.js (
sf-fx-sdk-nodejs) as a dependency in the
package.json file. This SDK provides a bunch of different pre-defined types and interfaces that you can import and use in your code. Thanks to these pre-defined types, you know precisely the shape of a parameter, property, or return type, which makes working with Salesforce data a lot easier.
You can even create your own types or import types from a third-party library if you are using one. For example, we can install the
node-fetch library (see docs) from npm and use the types defined by the library. In the below example, we are importing and using the
ReferrerPolicy type from the library.
Also, check out this TypeScript function recipe that returns the Salesforce org information attached to the context.
@salesforce/ts-types library (see docs) provides a collection of commonly desired types and a collection of type-narrowing functions for writing concise type-guards. For example, the
AnyJson type can be used to hold any untyped JSON object, and different functions like
getBoolean can get the value of a specific type from the JSON object.
The use of this library also ensures runtime type safety. Here is an example:
Salesforce CLI plug-ins
Built on top of OCLIF, a Salesforce CLI plug-in is created using TypeScript. This plugin also uses the
@salesforce/ts-types library mentioned earlier. You can also see the concept of generics in action when using the
query function from the JSforce library. In the below example, you can see that a custom interface
Organization has been created, and is explicitly set as the type to the generic
query function, which automatically sets the type of
One of the many ways to build Slack apps is to use Node.js with the
@slack/bolt library added as a dependency. You can easily add
typescript as an additional dependency and start using TypeScript to build Slack apps. Here is a sample Bolt app that is built using TypeScript. Similar to the Salesforce Function SDK for Node.js, the Bolt library also comes with a bunch of pre-defined types like
BlockAction, and many many more. The documentation for using TypeScript with Slack is a work in progress, so keep an eye out for updates.
The opportunities to use TypeScript with varying levels of strictness across different Salesforce products is gradually increasing, and hopefully, this blog post has given you a good glimpse into them. Now that you have seen how TypeScript can help you write robust code that will result in fewer runtime errors, how about giving it a try?
Here are some resources that will help you along the way:
- Types and tools for Salesforce TypeScript development
- Functions recipes
- Mulesoft’s DataWeave type system
- Getting started with TypeScript on Heroku
About the author
Aditya Naag Topalli is a 14x Certified Lead Developer Advocate at Salesforce. He empowers and inspires developers in and outside the Salesforce ecosystem through his videos, webinars, blog posts, and open source contributions, and he also frequently speaks at conferences and events all around the world. Follow him on Twitter or LinkedIn and check out his contributions on GitHub.