One JavaScript foundation
TypeScript builds on JavaScript: functions, objects, arrays, promises and runtime APIs still behave according to JavaScript rules. Most ordinary JavaScript syntax can be used in a TypeScript file. Learning JavaScript therefore remains useful even if a team writes TypeScript.
TypeScript adds a checker and optional type syntax to help developers reason about values before code runs. It does not fundamentally replace JavaScript. Browsers execute JavaScript output in the normal build workflow; Node.js is a JavaScript runtime too. Both languages need testing in the environment where the program will run.
The same greeting in both languages
Read these two versions together. Both call greet with Codectionary and log Hello, Codectionary. JavaScript has no parameter or return annotation here. TypeScript adds : string after name to describe the accepted input and after the closing parenthesis to describe the returned value. Those annotations help the checker and editor; they are not printed or used as runtime checks.
The function body and call are otherwise the same. If the call becomes greet(42), JavaScript permits it and concatenates the number into a greeting at runtime. A full TypeScript check reports that 42 is not assignable to the string parameter. TypeScript does not alter JavaScript string concatenation after its types are erased.
JavaScript source: greeting.js
function greet(name) {
return "Hello, " + name;
}
console.log(greet("Codectionary"));TypeScript source: greeting.ts
function greet(name: string): string {
return "Hello, " + name;
}
console.log(greet("Codectionary"));Dynamic values and static feedback
JavaScript values have types at runtime, but a variable can hold different kinds of values as the program runs. This is dynamic typing. A JavaScript editor may still provide suggestions or optional checks, but JavaScript itself does not require the : string declarations shown above.
TypeScript performs static type checking: it analyses source code before execution and reports mismatches. You can write an annotation such as name: string, or let TypeScript infer a type from a value, such as the number type of const visits = 3. Editors can use these types for completion, navigation, refactoring and early error messages. Inference reduces repetitive annotations; explicit types are useful at important boundaries such as public function parameters.
These checks describe assumptions in code. They cannot confirm that an API response or form value really has a declared shape at runtime. Validate untrusted inputs and test behaviour in either language.
Build workflow and browser compatibility
A JavaScript file can be run by a compatible browser or Node.js without a TypeScript compilation step. A conventional TypeScript project checks .ts or .tsx source and emits .js output before running it. A build tool might only remove types without performing the complete check, so confirm whether your workflow also runs tsc or another full checker.
For this greeting, the emitted JavaScript has the same behaviour as the JavaScript version above: the : string annotations disappear. More complex output depends on the compiler target and module settings. Browser compatibility depends on the emitted JavaScript syntax and the browser APIs used, not on the fact that the source was TypeScript. Standard browser script loading does not treat a .ts file containing annotations as ordinary JavaScript.
Some modern runtimes can strip supported TypeScript syntax and run certain .ts files directly. Their feature support differs, and stripping types does not perform full type checking. The portable beginner workflow is to check the project, produce JavaScript, then execute that JavaScript.
When should you choose each?
Choose plain JavaScript for a first browser page, a small script or a project where extra configuration would add more work than value. You can learn the core language and run it immediately. A JavaScript project can still adopt editor checks and JSDoc comments if that fits its needs.
Choose TypeScript when early feedback and documented data shapes help a growing application, shared API, library or team. It adds a checking and build workflow and can help with large changes, but it cannot make faulty logic correct. You can migrate a JavaScript codebase gradually rather than rewrite it all at once.
Syntax
function greet(name) {
return "Hello, " + name;
}
console.log(greet("Codectionary"));Examples
Run the JavaScript output
This is the JavaScript equivalent of the typed source above. The preview prints Hello, Codectionary.
function greet(name) {
return "Hello, " + name;
}
console.log(greet("Codectionary"));- greet takes a name and joins it to Hello, to form a greeting. console.log prints the result of calling greet with "Codectionary".
- Compare this with the TypeScript snippet above: the parameter and return type annotations have no runtime counterpart here.
- The browser and Node.js execute JavaScript. TypeScript checking can spot a mismatched call before this code runs, but the resulting JavaScript does not enforce the annotation.
Best practices
- Learn core JavaScript behaviour regardless of which authoring language you choose.
- Treat static type checks as early feedback, not runtime input validation.
- Run and test the emitted JavaScript in your target environment.
- Add TypeScript when its checking benefit justifies the extra tooling.
Runtime & versions
Browsers and JavaScript runtimes. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
ECMAScript specification