What is TypeScript and how is it different from JavaScript?
TypeScript is a general-purpose programming language developed and maintained by Microsoft. It is a superset of JavaScript, meaning all JavaScript code is valid TypeScript code. The key difference is that TypeScript adds static typing, allowing developers to declare variable types and catch errors at compile time. This helps improve code maintainability and reduces runtime errors. For more, see the TypeScript vs JavaScript article. Note: TypeScript requires a compilation step before running in browsers.
How popular is TypeScript among developers and companies?
TypeScript has seen significant adoption in recent years. According to GitHub's 2022 Octoverse report, TypeScript was the fourth most used programming language. Over 20,000 TypeScript-related positions were advertised on LinkedIn as of 2022. Major companies like Trivago and Stripe have migrated their technology stacks to TypeScript. The Stack Overflow survey showed TypeScript's popularity rising from 34.83% in 2022 to 38.87% in 2023. Note: Popularity may vary by region and industry.
What are the main features of TypeScript?
TypeScript offers static typing, optional typing, generics, advanced type system (including union, intersection, conditional, and mapped types), type aliases, interfaces, enums, and support for object-oriented programming. It also supports ES6 features like arrow functions and template literals, and provides tools for code organization such as modules and namespaces. Note: Some advanced features may require additional configuration or learning curve.
TypeScript in Practice
When should I use TypeScript for my project?
TypeScript is best suited for large-scale applications, projects requiring long-term maintenance, and teams with multiple developers. Its static typing helps catch errors early and improves collaboration. It is also valuable for projects where code maintainability and scalability are priorities. Note: For small or short-lived projects, the overhead of TypeScript may not be justified.
Are there situations where TypeScript is not recommended?
TypeScript may not be ideal for simple projects with minimal complexity, or for legacy codebases where migrating from JavaScript would require significant effort. For projects nearing end-of-life or with minimal maintenance, the benefits of TypeScript may not outweigh the migration cost. Note: The learning curve and configuration requirements may also be a barrier for some teams.
How do I set up TypeScript in my development environment?
To set up TypeScript locally, install Node.js and npm, then run npm install typescript --save-dev in your project directory. Use an IDE like VS Code for enhanced TypeScript support. Create TypeScript files with the .ts extension and compile them to JavaScript using the tsc command. For more details, see the TypeScript Handbook. Note: Some build tools or frameworks may require additional configuration.
TypeScript, GraphQL, and Hygraph
How does TypeScript integrate with GraphQL and Hygraph?
TypeScript and GraphQL are commonly used together in modern web development. Tools like GraphQL Code Generator can automatically generate TypeScript types from GraphQL schema definitions, simplifying development and ensuring type safety. Hygraph, as a GraphQL-native headless CMS, works well with TypeScript, allowing developers to build high-performance, maintainable applications. For more, see Hygraph's GraphQL resources. Note: Integration may require additional tooling or configuration depending on your stack.
What are the benefits of using TypeScript with Hygraph?
Using TypeScript with Hygraph enables developers to leverage static typing and type safety when interacting with Hygraph's GraphQL APIs. This reduces runtime errors, improves code maintainability, and streamlines collaboration in larger teams. Hygraph's GraphQL-native architecture and content federation features further enhance developer productivity. Note: Teams unfamiliar with TypeScript may require onboarding and training.
Advanced TypeScript Features
What advanced type system features does TypeScript offer?
TypeScript's advanced type system includes union types (variables that can hold multiple types), intersection types (combining multiple types), conditional types (types that depend on other types), mapped types (transforming properties of existing types), and type aliases (custom names for types). These features enable developers to write flexible, type-safe code for complex applications. Note: Advanced type features may increase code complexity and require deeper TypeScript knowledge.
How does TypeScript support object-oriented programming (OOP)?
TypeScript supports OOP concepts such as classes, interfaces, and inheritance. Classes define templates for objects, interfaces describe object shapes, and enums provide named constants. These features help organize and structure code for maintainability and scalability. Note: OOP features in TypeScript are similar to those in other statically typed languages, but may require adaptation for developers coming from JavaScript.
TypeScript Ecosystem and Tooling
What tools and IDEs are available for TypeScript development?
Popular tools for TypeScript development include the official TypeScript compiler (tsc), build tools like Webpack and Gulp, and IDEs such as Visual Studio Code, which offers features like IntelliSense, code completion, and debugging. The TypeScript community is active and provides support via forums and Discord. Note: Some tools may require additional configuration for optimal TypeScript support.
TypeScript and JavaScript Compatibility
Can TypeScript and JavaScript be used together in the same project?
Yes, TypeScript and JavaScript can coexist in the same project. JavaScript files can be gradually migrated to TypeScript by changing file extensions and adding type annotations. The TypeScript compiler and a tsconfig file are required for proper integration. Note: Some JavaScript code may require refactoring to fully leverage TypeScript's type system.
TypeScript Trends and Future
What is the future outlook for TypeScript?
TypeScript is actively developed by Microsoft and widely adopted in the industry. Frameworks like Next.js and Angular officially support TypeScript. The language's popularity continues to grow, as shown by developer surveys and industry adoption. For the latest roadmap, see the TypeScript roadmap. Note: JavaScript is also evolving, with proposals to add type annotations, which may influence future adoption patterns.
TypeScript, Hygraph, and Developer Community
How can I connect with other TypeScript and Hygraph developers?
You can join Hygraph's developer community to connect with TypeScript developers of all experience levels. The community shares best practices, answers questions, and provides support for building with TypeScript, GraphQL, and Hygraph. Visit Hygraph's developer community to get started. Note: Community resources may vary in depth and availability.
In this article, we will explore TypeScript from the ground up to understand its benefits, which have prompted its ever-growing usage in the developer community.
Last updated by Motunrayo
on Jan 21, 2026
Originally written by Motunrayo
TypeScript is a general-purpose programming language used across various development environments. Over the years since its release, it has gained much support from developers and companies, evidenced by GitHub ranking it as its fourth most used programming language of 2022. TypeScript’s prominence has increased since then.
Additionally, its popularity is reflected in the abundance of job opportunities, with over 20,000 TypeScript-related positions advertised on LinkedIn and major industry players, including Trivago and Stripe, opting to transition their technology stacks to TypeScript.
In this article, we will explore TypeScript from the ground up to understand its benefits, which have prompted its ever-growing usage in the developer community.
TypeScript is not entirely new; it's a superset of JavaScript that tackles limitations within JavaScript itself. As a superset, TypeScript extends JavaScript by adding static typing.
This static typing can be declared in two common ways:
1. Type annotations during declaration
This involves immediately specifying the variables and their type when the variable is first declared. Like so:
letname: string = "Hygraph
Where name is the variable name and string is the type.
2. Type aliases
This method involves defining a type separately using the type keyword and later using it to annotate variables.
Static typing refers to when variables are explicitly declared with their data types (like integer, string, boolean) at compile time, and the system performs type checking before the program runs.
While the behavior below is allowed in JavaScript, doing the same in TypeScript would cause an error because of TypeScript’s type enforcement.
While TypeScript allows explicit variable declaration, it also supports writing JavaScript-like code without declaring the types; TypeScript will infer the type out of the box. E.g.,
let name ="Hygraph";
In the above, TypeScript will infer that the type name is a string through the variable initialization value, i.e., “Hygraph.”
TypeScript generics
By parameterizing types and functions, TypeScript generics create reusable components and functions that can work with various types without compromising the type safety:
// Generic function to return the length of an array
function getArrayLength<T>(array:T[]): number {
return array.length;
}
// Using the generic function with different types of arrays
TypeScript's type system goes beyond basic static typing. It also provides features for defining complex types, manipulating types, establishing relationships between variables, enforcing type constraints, and other functionalities, which allows for developing error-free applications.
Let us consider some of the most commonly used advanced types.
1. Union types
Union in TypeScript refers to declaring a variable or function argument holding numerous data types. This can be beneficial when a value has different data types at runtime.
Union types are represented with the | symbol, which separates the data types. E.g.:
let age = number | string;
age =10;
age ="ten";
As seen above, we could specify that the age variable could possess two data types. This provides flexibility without endangering type safety.
2. Intersection types
Intersections allow the creation of a new type by combining multiple existing types into one. This new type has the properties and functionalities of the combined types.
Intersections are created by using the & symbol between the types to be combined. E.g.:
interfaceUser{
id: number;
username: string;
email: string;
}
interfaceAdmin{
isAdmin: boolean;
}
// A new type using intersection type
type UserAndAdmin=User&Admin;
Here, the type UserAndAdmin combines the properties of both User and Admin interfaces to produce a type that requires all the properties from both.
3. Conditional types
Conditional types in TypeScript create types that depend on a state, which allows for the definition of dynamic types that change based on the properties of other types, values, or contexts.
Let us consider a basic example:
// A conditional type to determine if a type is an array
type IsArray<T>=Textendsany[]?true:false;
// Test the conditional type with different types
type Result1=IsArray<number>;// false
type Result2=IsArray<string[]>;// true
type Result3=IsArray<boolean |[]>;// true
Conditional types are defined using the ternary operator (? :) syntax within the angle brackets (<>) known as “generic type parameter”- more on this later in the article. They also use the extends keyword, which checks if a type meets a certain condition and produces a different type based on the result of that condition.
4. Mappedn types
Mapped types in TypeScript allow the creation of new types by transforming the properties of existing types. They do this by iterating over the properties of a source type and applying a transformation to each property to generate a new type. E.g.:
// type representing a user
type User={
id: number;
username: string;
email: string;
};
// Mapped type to make all properties optional
type OptionalUser={[Pin keyof User]?:User[P]};
// New type using the mapped type
constoptionalUser:OptionalUser={id:1};
// Property 'email' is now optional
optionalUser.username="john_doe";
// Property 'id' is still required
// optionalUser.email = "john@example.com"; // Error: Property 'email' is missing
Mapped types are defined using { [P in keyof Type]: NewType } syntax, where Type is the source type, P is the property key, and NewType is the transformed type. P iterates over the property keys, and transformation defines the change.
5. Type aliases
Type aliases allow the creation of custom names (aliases) for existing TypeScript types, including primitives, union types, intersection types, and even more complex types like object literals and function types. Type aliases are defined using the type keyword followed by the new name, as shown below:
// type alias for a union type
type Result="success"|"error";
// type alias for an object literal
type Point={x: number; y: number };
// type alias for a function type
type Greeting=(name: string)=> string;
// Using the type aliases
conststatus:Result="success";
constorigin:Point={x:0,y:0};
constgreet:Greeting=(name)=>Hello, ${name}!;
The code above shows different use cases of type aliases for different types in TypeScript and their usage after declaration.
OOP is a paradigm based on the concept of "objects" interacting to create maintainable and reusable code.
1. TypeScript classes
Classes are templates or blueprints for creating objects i.e., they define the data (properties) and methods (functions).
Here is an example of how a class implementation will look in TypeScript:
classOrganization{
privatename: string;
privateyearFounded: number;
constructor(name: string,yearFounded: number){
this.name= name;
this.yearFounded= yearFounded;
}
publicgetDetails(): string {
return`${this.name} was founded in ${this.yearFounded}.`;
}
}
let organization =newOrganization("Hygraph",2015);
console.log(organization.name);// Error: Property 'name' is private and only accessible within class 'Organization'.
console.log(organization.getDetails());// Output: Hygraph was founded in 2015
In the code above, we created a class Organization with private properties name and yearFounded, which can only be accessed and modified within the “Organization” class. Notice how we typed the properties and methods.
2. TypeScript interface
Interfaces describe the shape of objects by listing the properties and methods they should have without providing any implementation details:
// Interface representing form data
interfaceFormData{
firstName: string;
lastName: string;
email: string;
age: number;
}
// Usage
letformData:FormData={
firstName:"John",
lastName:"Doe",
email:"john.doe@example.com",
age:30
};
In the example above, we defined an interface FormData representing the structure of form data.
Next, we created an object formData with properties corresponding to the interface definition.
TypeScript enums
Enumerate types, represented with enum in TypeScript, are a set of named constants enclosed in curly braces {}, where each constant has an associated numeric or string value.
A typical TypeScript enum set could look like this:
// enum for days of the week
enumDayOfWeek{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
enumHTTPStatusCodes{
OK=200,
BadRequest=400,
NotFound=404,
}
The code block above immediately explains what is happening, showcasing the semantic meaning-adding advantage of using TypeScript enums.
TypeScript supports many ECMAScript 6 (ES6) features, also known as ECMAScript 2015. Some of these features include:
1) Arrow functions: Unlike traditional function expressions, arrow functions provide a straightforward syntax for defining functions. They offer an implicit return for single-line expressions and automatic binding of this and can be useful for callback functions or event handlers.
// Arrow function
constadd=(x, y)=> x + y;
// Traditional function expression
constadd=function(x, y){
return x + y;
};
2) Template literals: This allows embedding expressions and multiline strings directly within backticks (``) in the code. This makes creating dynamic strings, including interpolating variables and expressions, **easy.
constname: string ="John";
constgreeting: string =`Hello, ${name}!`;
There are more ES6 features than this article can explore. Visit Ecma Internation to learn more.
Proper code organization in TypeScript or any other language is essential for maintaining clean, maintainable, and scalable projects. However, TypeScript simplifies this by providing out-of-the-box support for properly organizing code, such as:
1. Modules
Modules, introduced in ES6 as part of the language specification, using the import and export statements, developers can organize code into reusable components, libraries, or features, ensuring separation of concerns, readability, and reusability.
// math.ts
exportfunctionadd(x: number,y: number): number {
return x + y;
}
// app.ts
import{ add }from"./math";
Here, we created an add function and exported it using the export statement for usage across the codebase.
2. Namespace
This helps to logically group related code under a single, global hierarchy, especially for shared utility functions or types across multiple modules in a project. This can be useful in large codebases to help prevent naming conflicts or global scope pollution as the codebase becomes larger.
namespace Geometry{
exportclassCircle{
// Circle implementation
}
exportclassRectangle{
// Rectangle implementation
}
}
The code above creates a namespace called Geometry that acts like a container for two related classes, Circle and Rectangle. These classes can be used in other parts of the code by importing them from the Geometry namespace, like so:
import{Circle,Rectangle}from'./Geometry';// Import from Geometry namespace
const myCircle =newCircle();// Create a Circle object
const myRectangle =newRectangle();// Create a Rectangle object
Integrating TypeScript with existing JavaScript libraries offers a way of leveraging TypeScript's benefits of type safety while using the JavaScript library ecosystem.
TypeScript does this in the following ways:
Declaration files: Declaration files are blueprints that describe the shape of the library's API (functions, classes, objects, and types).
TypeScript support: Many popular JavaScript libraries and frameworks also officially support TypeScript by providing TypeScript-specific installation instructions. Some also take it a step further by providing plugins specifically developed for TypeScript development libraries.
Browsers only understand and execute JavaScript code. As a result, to run TypeScript code in the browser, it must first be compiled/transpiled into JavaScript using the TypeScript compilertsc, which transforms any TypeScript-specific features into code compatible with JavaScript engines.
The compilation process is like this:
Parsing: The compiler starts by reading the TypeScript code and parsing or transforming it into a data structure called an Abstract Syntax Tree (AST), which represents the code's structure and relationships between elements.
Type checking: During parsing, the compiler performs type checking based on type annotations and inference to ensure the code adheres to the defined types.
Transformation: The compiler might transform the code based on the AST and type-checking results. This could involve removing type annotations as they are not needed in JavaScript.
Code generation: The compiler generates the equivalent JavaScript code based on the transformed AST, which retains the functionality of the TypeScript code.
Let us look at this TypeScript code which defines an Admin interface and a createAdmin function that matches the interface properties.
JavaScript and TypeScript syntax can coexist in the same project. However, to leverage TypeScript’s capabilities, the TypeScript compiler must be set up.
This compatibility offers several advantages for developers:
Syntax compatibility: JavaScript codebases can be gradually migrated to TypeScript. Changing the file extension from .js to .ts is a starting point; it also requires a TypeScript compiler and a tsconfig file that specifies the compiler options.
Type compatibility: TypeScript provides a type system that allows developers to specify variable types. However, TypeScript also supports dynamic typing, allowing developers to opt in or out of type-checking.
Runtime compatibility: Since TypeScript code is transpiled to JavaScript before execution, it is compatible with any JavaScript runtime environment.
The first step in working with TypeScript locally (i.e., offline) is to set up your environment. TypeScript can be set up in three ways, but in this section, we will consider just one: via npm.
Setup
First, you must install Node to run the environment and NPM to manage dependency. Download them from the Node.js official website.
Next, use an IDE like VS Code and initialize a new project with npm by running npm init -y, which will create a package.json for the project.
Within this project, run npm install typescript --save-dev to install TypeScript as a dependency for development purposes only.
Writing TypeScript code
Now, write your first TypeScript program by creating a file named app.ts . ts is the file extension for TypeScript as .js is the extension for JavaScript files.
Now, add this code that defines an Admin interface with name and id properties into the app.ts file:
In the code above, after defining the interface, we also created a function createAdmin, which creates “Admin” objects.
Compiling TypeScript code
To compile this file using the tsc TypeScript compiler, run npx tscapp.ts in the terminal. This will create a file named app.js alongside the app.ts file.
To watch for changes and automatically recompile the TypeScript file, run **npx tsc app.ts****--****watch** in your terminal.
You can modify the code and write more TypeScript code following some of the features we discussed earlier.
The best way to learn TypeScript is to practice writing it, experiment with different features and patterns, and build projects. The TypeScript handbook explains the various features TypeScript offers and how you can leverage them. You can also read this article about using TypeScript with Svelte.
Since TypeScript’s release over a decade ago, there has been continuous debate over its advantages over JavaScript.
In this section, we will explore some of these advantages.
Type safety: TypeScript's static type system enforces type annotations on variables, functions, and objects, which helps to achieve early error detection and improved maintainability through interfaces, classes, and modules.
Better developer experience: Developers can now write code more confidently, knowing that the compiler will identify potential type mismatches before the code reaches runtime. This can be especially useful when migrating a JavaScript codebase to TypeScript.
From the trade-offs explored above, you can deduce that TypeScript may not be appropriate for all projects. This may be true, but why do we leave that decision to you? Let’s help you make a better decision.
When is it appropriate to use TypeScript?
Large-scale applications: TypeScript was developed to address scalability problems of large JavaScript codebases. As a project grows, static typing helps catch errors early and improves code maintainability and collaboration among team members.
Team collaboration: In a team environment with multiple developers contributing to the same codebase, TypeScript can facilitate collaboration by enforcing coding conventions and enabling better communication through self-documenting code.
Long-term projects: Maintenance is the last phase of the software development lifecycle and can take as long as a decade or as short as a year. TypeScript is well-suited for long-term projects where code maintenance, scalability, and future-proofing are essential considerations.
Unfortunately, despite its advantages, TypeScript might not suit all use cases. Such as:
Simple projects: For small projects with minimal complexity, the benefits of static typing and advanced tooling may not outweigh the additional configuration and learning curve associated with TypeScript.
Legacy codebases: Converting large, existing JavaScript codebases to TypeScript can be daunting. In such cases, the effort required to migrate to TypeScript might not justify the benefits, particularly if the project is nearing its end-of-life or undergoing minimal maintenance.
TypeScript's ecosystem has a rich toolset of libraries and frameworks, which can be leveraged for a better development experience. Such as:
TypeScript compiler (tsc): The TypeScript compiler (tsc) is the primary and official tool for transpiling TypeScript code into JavaScript code.
**Integrated Development Environments (IDEs): Many IDEs, such as VS Code, offer excellent support for TypeScript development. These features range from intellisense to code completion and debugging functionalities.
TypeScript community: TypeScript has a large and growing community that allows asking questions, sharing knowledge, and learning from other TypeScript developers.
Build tools: Using TypeScript requires compiling it into JavaScript, so bundling tools that automate the compilation process exist. Examples of these build tools are Webpack, Gulp, etc.
TypeScript and GraphQL are powerful tools commonly used together in modern web development. GraphQL, a query language for APIs, provides a flexible and efficient approach to data fetching and manipulation. Combined, TypeScript and GraphQL offer numerous benefits for building robust and scalable applications. Such as:
Intuitive type generation: Tools like GraphQL code generator can automatically generate TypeScript types from GraphQL schema definitions, which can significantly simplify development.
Strong typing with GraphQL schema: TypeScript's static typing aligns well with GraphQL's schema-based approach.
In essence, while TypeScript ensures type safety, GraphQL provides flexibility in data fetching. TypeScript and GraphQL work perfectly with a headless content management system (CMS) like Hygraph. Developers can combine all three technologies to create high-performance, maintainable, and rich user interfaces. If you are evaluating how Hygraph compares to other platforms in the ecosystem, check out our comparisons for Hygraph vs Contentful, Hygraph vs Sanity, or Contentstack.
TypeScript is actively developed and maintained by Microsoft and has widespread industry adoption. Currently, popular frameworks like Next.js advocate for TypeScript as the modern tool for web development through the TypeScript first configuration details. Same as Angular - an open-source framework whose official language is TypeScript.
We can expect to see even more progression and adoption over the years. Check out this page to learn more about the TypeScript roadmap.
Developers, TypeScript’s target audience, have also shared their continuous favoritism toward it. The Stackoverflow survey also corroborates this, showing that TypeScript rose from 34.83% in 2022 to 38.87% in 2023 as a popular language.
However, we also see continuous upgrades to JavaScript, with the latest proposition to add type annotations to JavaScript. But are types all that is needed to make developers quit TypeScript for JavaScript? We guess time will tell.
Join Hygraph's developer community to connect with other TypeScript developers, from beginners to experts. Learn best practices and leverage the language's full potential.
Blog Author
Motunrayo Moronfolu
Technical writer
Motunrayo Moronfolu is a Senior Frontend Engineer and Technical writer passionate about building and writing about great user experiences.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.
In this article, we will explore TypeScript from the ground up to understand its benefits, which have prompted its ever-growing usage in the developer community.
Last updated by Motunrayo
on Jan 21, 2026
Originally written by Motunrayo
TypeScript is a general-purpose programming language used across various development environments. Over the years since its release, it has gained much support from developers and companies, evidenced by GitHub ranking it as its fourth most used programming language of 2022. TypeScript’s prominence has increased since then.
Additionally, its popularity is reflected in the abundance of job opportunities, with over 20,000 TypeScript-related positions advertised on LinkedIn and major industry players, including Trivago and Stripe, opting to transition their technology stacks to TypeScript.
In this article, we will explore TypeScript from the ground up to understand its benefits, which have prompted its ever-growing usage in the developer community.
TypeScript is not entirely new; it's a superset of JavaScript that tackles limitations within JavaScript itself. As a superset, TypeScript extends JavaScript by adding static typing.
This static typing can be declared in two common ways:
1. Type annotations during declaration
This involves immediately specifying the variables and their type when the variable is first declared. Like so:
letname: string = "Hygraph
Where name is the variable name and string is the type.
2. Type aliases
This method involves defining a type separately using the type keyword and later using it to annotate variables.
Static typing refers to when variables are explicitly declared with their data types (like integer, string, boolean) at compile time, and the system performs type checking before the program runs.
While the behavior below is allowed in JavaScript, doing the same in TypeScript would cause an error because of TypeScript’s type enforcement.
While TypeScript allows explicit variable declaration, it also supports writing JavaScript-like code without declaring the types; TypeScript will infer the type out of the box. E.g.,
let name ="Hygraph";
In the above, TypeScript will infer that the type name is a string through the variable initialization value, i.e., “Hygraph.”
TypeScript generics
By parameterizing types and functions, TypeScript generics create reusable components and functions that can work with various types without compromising the type safety:
// Generic function to return the length of an array
function getArrayLength<T>(array:T[]): number {
return array.length;
}
// Using the generic function with different types of arrays
TypeScript's type system goes beyond basic static typing. It also provides features for defining complex types, manipulating types, establishing relationships between variables, enforcing type constraints, and other functionalities, which allows for developing error-free applications.
Let us consider some of the most commonly used advanced types.
1. Union types
Union in TypeScript refers to declaring a variable or function argument holding numerous data types. This can be beneficial when a value has different data types at runtime.
Union types are represented with the | symbol, which separates the data types. E.g.:
let age = number | string;
age =10;
age ="ten";
As seen above, we could specify that the age variable could possess two data types. This provides flexibility without endangering type safety.
2. Intersection types
Intersections allow the creation of a new type by combining multiple existing types into one. This new type has the properties and functionalities of the combined types.
Intersections are created by using the & symbol between the types to be combined. E.g.:
interfaceUser{
id: number;
username: string;
email: string;
}
interfaceAdmin{
isAdmin: boolean;
}
// A new type using intersection type
type UserAndAdmin=User&Admin;
Here, the type UserAndAdmin combines the properties of both User and Admin interfaces to produce a type that requires all the properties from both.
3. Conditional types
Conditional types in TypeScript create types that depend on a state, which allows for the definition of dynamic types that change based on the properties of other types, values, or contexts.
Let us consider a basic example:
// A conditional type to determine if a type is an array
type IsArray<T>=Textendsany[]?true:false;
// Test the conditional type with different types
type Result1=IsArray<number>;// false
type Result2=IsArray<string[]>;// true
type Result3=IsArray<boolean |[]>;// true
Conditional types are defined using the ternary operator (? :) syntax within the angle brackets (<>) known as “generic type parameter”- more on this later in the article. They also use the extends keyword, which checks if a type meets a certain condition and produces a different type based on the result of that condition.
4. Mappedn types
Mapped types in TypeScript allow the creation of new types by transforming the properties of existing types. They do this by iterating over the properties of a source type and applying a transformation to each property to generate a new type. E.g.:
// type representing a user
type User={
id: number;
username: string;
email: string;
};
// Mapped type to make all properties optional
type OptionalUser={[Pin keyof User]?:User[P]};
// New type using the mapped type
constoptionalUser:OptionalUser={id:1};
// Property 'email' is now optional
optionalUser.username="john_doe";
// Property 'id' is still required
// optionalUser.email = "john@example.com"; // Error: Property 'email' is missing
Mapped types are defined using { [P in keyof Type]: NewType } syntax, where Type is the source type, P is the property key, and NewType is the transformed type. P iterates over the property keys, and transformation defines the change.
5. Type aliases
Type aliases allow the creation of custom names (aliases) for existing TypeScript types, including primitives, union types, intersection types, and even more complex types like object literals and function types. Type aliases are defined using the type keyword followed by the new name, as shown below:
// type alias for a union type
type Result="success"|"error";
// type alias for an object literal
type Point={x: number; y: number };
// type alias for a function type
type Greeting=(name: string)=> string;
// Using the type aliases
conststatus:Result="success";
constorigin:Point={x:0,y:0};
constgreet:Greeting=(name)=>Hello, ${name}!;
The code above shows different use cases of type aliases for different types in TypeScript and their usage after declaration.
OOP is a paradigm based on the concept of "objects" interacting to create maintainable and reusable code.
1. TypeScript classes
Classes are templates or blueprints for creating objects i.e., they define the data (properties) and methods (functions).
Here is an example of how a class implementation will look in TypeScript:
classOrganization{
privatename: string;
privateyearFounded: number;
constructor(name: string,yearFounded: number){
this.name= name;
this.yearFounded= yearFounded;
}
publicgetDetails(): string {
return`${this.name} was founded in ${this.yearFounded}.`;
}
}
let organization =newOrganization("Hygraph",2015);
console.log(organization.name);// Error: Property 'name' is private and only accessible within class 'Organization'.
console.log(organization.getDetails());// Output: Hygraph was founded in 2015
In the code above, we created a class Organization with private properties name and yearFounded, which can only be accessed and modified within the “Organization” class. Notice how we typed the properties and methods.
2. TypeScript interface
Interfaces describe the shape of objects by listing the properties and methods they should have without providing any implementation details:
// Interface representing form data
interfaceFormData{
firstName: string;
lastName: string;
email: string;
age: number;
}
// Usage
letformData:FormData={
firstName:"John",
lastName:"Doe",
email:"john.doe@example.com",
age:30
};
In the example above, we defined an interface FormData representing the structure of form data.
Next, we created an object formData with properties corresponding to the interface definition.
TypeScript enums
Enumerate types, represented with enum in TypeScript, are a set of named constants enclosed in curly braces {}, where each constant has an associated numeric or string value.
A typical TypeScript enum set could look like this:
// enum for days of the week
enumDayOfWeek{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
enumHTTPStatusCodes{
OK=200,
BadRequest=400,
NotFound=404,
}
The code block above immediately explains what is happening, showcasing the semantic meaning-adding advantage of using TypeScript enums.
TypeScript supports many ECMAScript 6 (ES6) features, also known as ECMAScript 2015. Some of these features include:
1) Arrow functions: Unlike traditional function expressions, arrow functions provide a straightforward syntax for defining functions. They offer an implicit return for single-line expressions and automatic binding of this and can be useful for callback functions or event handlers.
// Arrow function
constadd=(x, y)=> x + y;
// Traditional function expression
constadd=function(x, y){
return x + y;
};
2) Template literals: This allows embedding expressions and multiline strings directly within backticks (``) in the code. This makes creating dynamic strings, including interpolating variables and expressions, **easy.
constname: string ="John";
constgreeting: string =`Hello, ${name}!`;
There are more ES6 features than this article can explore. Visit Ecma Internation to learn more.
Proper code organization in TypeScript or any other language is essential for maintaining clean, maintainable, and scalable projects. However, TypeScript simplifies this by providing out-of-the-box support for properly organizing code, such as:
1. Modules
Modules, introduced in ES6 as part of the language specification, using the import and export statements, developers can organize code into reusable components, libraries, or features, ensuring separation of concerns, readability, and reusability.
// math.ts
exportfunctionadd(x: number,y: number): number {
return x + y;
}
// app.ts
import{ add }from"./math";
Here, we created an add function and exported it using the export statement for usage across the codebase.
2. Namespace
This helps to logically group related code under a single, global hierarchy, especially for shared utility functions or types across multiple modules in a project. This can be useful in large codebases to help prevent naming conflicts or global scope pollution as the codebase becomes larger.
namespace Geometry{
exportclassCircle{
// Circle implementation
}
exportclassRectangle{
// Rectangle implementation
}
}
The code above creates a namespace called Geometry that acts like a container for two related classes, Circle and Rectangle. These classes can be used in other parts of the code by importing them from the Geometry namespace, like so:
import{Circle,Rectangle}from'./Geometry';// Import from Geometry namespace
const myCircle =newCircle();// Create a Circle object
const myRectangle =newRectangle();// Create a Rectangle object
Integrating TypeScript with existing JavaScript libraries offers a way of leveraging TypeScript's benefits of type safety while using the JavaScript library ecosystem.
TypeScript does this in the following ways:
Declaration files: Declaration files are blueprints that describe the shape of the library's API (functions, classes, objects, and types).
TypeScript support: Many popular JavaScript libraries and frameworks also officially support TypeScript by providing TypeScript-specific installation instructions. Some also take it a step further by providing plugins specifically developed for TypeScript development libraries.
Browsers only understand and execute JavaScript code. As a result, to run TypeScript code in the browser, it must first be compiled/transpiled into JavaScript using the TypeScript compilertsc, which transforms any TypeScript-specific features into code compatible with JavaScript engines.
The compilation process is like this:
Parsing: The compiler starts by reading the TypeScript code and parsing or transforming it into a data structure called an Abstract Syntax Tree (AST), which represents the code's structure and relationships between elements.
Type checking: During parsing, the compiler performs type checking based on type annotations and inference to ensure the code adheres to the defined types.
Transformation: The compiler might transform the code based on the AST and type-checking results. This could involve removing type annotations as they are not needed in JavaScript.
Code generation: The compiler generates the equivalent JavaScript code based on the transformed AST, which retains the functionality of the TypeScript code.
Let us look at this TypeScript code which defines an Admin interface and a createAdmin function that matches the interface properties.
JavaScript and TypeScript syntax can coexist in the same project. However, to leverage TypeScript’s capabilities, the TypeScript compiler must be set up.
This compatibility offers several advantages for developers:
Syntax compatibility: JavaScript codebases can be gradually migrated to TypeScript. Changing the file extension from .js to .ts is a starting point; it also requires a TypeScript compiler and a tsconfig file that specifies the compiler options.
Type compatibility: TypeScript provides a type system that allows developers to specify variable types. However, TypeScript also supports dynamic typing, allowing developers to opt in or out of type-checking.
Runtime compatibility: Since TypeScript code is transpiled to JavaScript before execution, it is compatible with any JavaScript runtime environment.
The first step in working with TypeScript locally (i.e., offline) is to set up your environment. TypeScript can be set up in three ways, but in this section, we will consider just one: via npm.
Setup
First, you must install Node to run the environment and NPM to manage dependency. Download them from the Node.js official website.
Next, use an IDE like VS Code and initialize a new project with npm by running npm init -y, which will create a package.json for the project.
Within this project, run npm install typescript --save-dev to install TypeScript as a dependency for development purposes only.
Writing TypeScript code
Now, write your first TypeScript program by creating a file named app.ts . ts is the file extension for TypeScript as .js is the extension for JavaScript files.
Now, add this code that defines an Admin interface with name and id properties into the app.ts file:
In the code above, after defining the interface, we also created a function createAdmin, which creates “Admin” objects.
Compiling TypeScript code
To compile this file using the tsc TypeScript compiler, run npx tscapp.ts in the terminal. This will create a file named app.js alongside the app.ts file.
To watch for changes and automatically recompile the TypeScript file, run **npx tsc app.ts****--****watch** in your terminal.
You can modify the code and write more TypeScript code following some of the features we discussed earlier.
The best way to learn TypeScript is to practice writing it, experiment with different features and patterns, and build projects. The TypeScript handbook explains the various features TypeScript offers and how you can leverage them. You can also read this article about using TypeScript with Svelte.
Since TypeScript’s release over a decade ago, there has been continuous debate over its advantages over JavaScript.
In this section, we will explore some of these advantages.
Type safety: TypeScript's static type system enforces type annotations on variables, functions, and objects, which helps to achieve early error detection and improved maintainability through interfaces, classes, and modules.
Better developer experience: Developers can now write code more confidently, knowing that the compiler will identify potential type mismatches before the code reaches runtime. This can be especially useful when migrating a JavaScript codebase to TypeScript.
From the trade-offs explored above, you can deduce that TypeScript may not be appropriate for all projects. This may be true, but why do we leave that decision to you? Let’s help you make a better decision.
When is it appropriate to use TypeScript?
Large-scale applications: TypeScript was developed to address scalability problems of large JavaScript codebases. As a project grows, static typing helps catch errors early and improves code maintainability and collaboration among team members.
Team collaboration: In a team environment with multiple developers contributing to the same codebase, TypeScript can facilitate collaboration by enforcing coding conventions and enabling better communication through self-documenting code.
Long-term projects: Maintenance is the last phase of the software development lifecycle and can take as long as a decade or as short as a year. TypeScript is well-suited for long-term projects where code maintenance, scalability, and future-proofing are essential considerations.
Unfortunately, despite its advantages, TypeScript might not suit all use cases. Such as:
Simple projects: For small projects with minimal complexity, the benefits of static typing and advanced tooling may not outweigh the additional configuration and learning curve associated with TypeScript.
Legacy codebases: Converting large, existing JavaScript codebases to TypeScript can be daunting. In such cases, the effort required to migrate to TypeScript might not justify the benefits, particularly if the project is nearing its end-of-life or undergoing minimal maintenance.
TypeScript's ecosystem has a rich toolset of libraries and frameworks, which can be leveraged for a better development experience. Such as:
TypeScript compiler (tsc): The TypeScript compiler (tsc) is the primary and official tool for transpiling TypeScript code into JavaScript code.
**Integrated Development Environments (IDEs): Many IDEs, such as VS Code, offer excellent support for TypeScript development. These features range from intellisense to code completion and debugging functionalities.
TypeScript community: TypeScript has a large and growing community that allows asking questions, sharing knowledge, and learning from other TypeScript developers.
Build tools: Using TypeScript requires compiling it into JavaScript, so bundling tools that automate the compilation process exist. Examples of these build tools are Webpack, Gulp, etc.
TypeScript and GraphQL are powerful tools commonly used together in modern web development. GraphQL, a query language for APIs, provides a flexible and efficient approach to data fetching and manipulation. Combined, TypeScript and GraphQL offer numerous benefits for building robust and scalable applications. Such as:
Intuitive type generation: Tools like GraphQL code generator can automatically generate TypeScript types from GraphQL schema definitions, which can significantly simplify development.
Strong typing with GraphQL schema: TypeScript's static typing aligns well with GraphQL's schema-based approach.
In essence, while TypeScript ensures type safety, GraphQL provides flexibility in data fetching. TypeScript and GraphQL work perfectly with a headless content management system (CMS) like Hygraph. Developers can combine all three technologies to create high-performance, maintainable, and rich user interfaces. If you are evaluating how Hygraph compares to other platforms in the ecosystem, check out our comparisons for Hygraph vs Contentful, Hygraph vs Sanity, or Contentstack.
TypeScript is actively developed and maintained by Microsoft and has widespread industry adoption. Currently, popular frameworks like Next.js advocate for TypeScript as the modern tool for web development through the TypeScript first configuration details. Same as Angular - an open-source framework whose official language is TypeScript.
We can expect to see even more progression and adoption over the years. Check out this page to learn more about the TypeScript roadmap.
Developers, TypeScript’s target audience, have also shared their continuous favoritism toward it. The Stackoverflow survey also corroborates this, showing that TypeScript rose from 34.83% in 2022 to 38.87% in 2023 as a popular language.
However, we also see continuous upgrades to JavaScript, with the latest proposition to add type annotations to JavaScript. But are types all that is needed to make developers quit TypeScript for JavaScript? We guess time will tell.
Join Hygraph's developer community to connect with other TypeScript developers, from beginners to experts. Learn best practices and leverage the language's full potential.
Blog Author
Motunrayo Moronfolu
Technical writer
Motunrayo Moronfolu is a Senior Frontend Engineer and Technical writer passionate about building and writing about great user experiences.
Share with others
Sign up for our newsletter!
Be the first to know about releases and industry news and insights.