Javascript-Typescript difference
- Type system:
- 1. Type Annotations
- 2. Type Coercion, strict type checking
- 3. Compiler time Type Narrowing (TS-Only)
- 4. JSON Parsing with type assertion
- 5. Type Imports (TS only)
- 6. Type-safe dynamic import (TS only)
- 7. User-Defined Type Guards
- 8. Define API Response type
- Array:
- 9. Tuple Types (TS-Only)
- 10. Compiler time Array Methods checking (TS-Only)
- 11. Array Type Safety (TS only)
- 12. Immutable Readonly Arrays (TS only)
- Function:
- 13. Function Typing (TS only)
- 14. Function Overloads (TS only)
- Enums:
- 15. Enums (TS only)
- 16. Enum Reverse Mapping (TS only)
- This:
- 17. Explicit this binding vs dynamic this
- Property:
- 18. Access Modifiers
- 19. Parameter Properties (TS only)
- 20. Method Overloading (TS only)
- 21. Property Initialization (TS only)
- 22. Property Declaration
- 23. Autodeclaration variable in constructor
- 24. Property Accessors (Getters/Setters)
- 25. Static Properties
- 26. Readonly Properties
- 28. Index properties
- Class inheritance:
- 29. Abstract Abstract Classes and Methods (TS only)
- 30. Inheritance and Overriding
- Interface:
- 31. Interface Implementation (TS only)
- Generic:
- 32. Generic Classes (TS only)
- Decorator:
- 33. Decorators (TS only)
- Immutable Objects:
- 34. Immutable Objects
- Operators:
- 35. Keyof Operator (TS only)
- 36. Optional Chaining (?.) vs TypeScript's Optional Properties
- 37. Non-Null Assertion Operator (!)
- 38. Strict Null Checks (TS only)
- Type manipulation:
- 39. Type Aliases (TS only)
- 40. Union Types (TS only)
- 41. Intersection Types (TS only)
- 42. Type Assertions (TS only)
- 43. Utility Types (Partial<T>, Pick<T, K>) (TS only)
- 44. Conditional Types (T extends U ? X : Y) (TS only)
- 45. Branded Types (nominal typing) (TS only)
- Execute TS:
Type system:
1. Type Annotations
1:
2: class Person {
3: name: string;
4: age: number;
5:
6: constructor(name: string, age: number) {
7: this.name = name;
8: this.age = age;
9: }
10: }
11:
1:
2: class Person {
3: constructor(name, age) {
4: this.name = name;
5: this.age = age;
6: }
7: }
8:
2. Type Coercion, strict type checking
1:
2: class Example {
3: value: number;
4:
5: constructor(value: number) {
6: this.value = value + "5"; // Error: can't concatenate number with string
7: }
8: }
9:
1:
2: class Example {
3: constructor(value) {
4: this.value = value + "5"; // type coercion: "55" if value is 5
5: }
6: }
7:
3. Compiler time Type Narrowing (TS-Only)
1:
2: function printLength(obj: string | string[]) {
3: if (typeof obj === "string") {
4: console.log(obj.length); // TS knows obj is string here
5: } else {
6: console.log(obj.length); // TS knows obj is array here
7: }
8: }
9:
1:
2: function printLength(obj) {
3: // No automatic type narrowing
4: if (typeof obj === "string") {
5: console.log(obj.length);
6: } else {
7: // ❌ Risky: obj could be anything
8: console.log(obj.length);
9: }
10: }
11:
4. JSON Parsing with type assertion
1:
2: const data = JSON.parse('{"name":"Alice"}') as { name: string };
3: console.log(data.age); // Property 'age' does not exist
4:
5. Type Imports (TS only)
1:
2: // types.ts
3: export type User = { name: string; age: number };
4:
5: // app.ts
6: import type { User } from './types'; // Only imports the type (erased at runtime)
7:
8: const user: User = { name: "Alice", age: 30 }; // Type usage
9:
6. Type-safe dynamic import (TS only)
1:
2: const module = await import('./module') as typeof import('./module');
3:
1:
2: const module = await import('./module'); // Anything goes
3:
7. User-Defined Type Guards
1:
2: function isCat(animal: Animal): animal is Cat {
3: return animal.type === "cat";
4: }
5: if (isCat(animal)) {
6: animal.meow(); // TS knows animal is Cat here
7: }
8:
1:
2: function isCat(animal) {
3: return animal.type === "cat";
4: }
5: if (isCat(animal)) {
6: animal.meow(); // No guarantee has meow() method
7: }
8:
8. Define API Response type
1:
2: interface User { id: number; name: string }
3: fetch('/user').then(res => res.json() as Promise<User>);
4:
1:
2: fetch('/user').then(res => res.json()); // Could be anything
3:
Array:
9. Tuple Types (TS-Only)
1:
2: let coordinates: [number, number] = [10, 20];
3: coordinates = [30, 40]; //
4: coordinates = [10, "20"]; // Error: string not assignable to number
5: coordinates = [10]; // Error:
6:
1:
2: let coordinates = [10, 20];
3: coordinates = [30, 40]; /
4: coordinates = [10, "20"]; // JS allows mixed types
5:
10. Compiler time Array Methods checking (TS-Only)
1:
2: const numbers = [1, 2, 3];
3: numbers.map(num => num.toUpperCase()); // toUpperCase doesn't exist on numbers
4:
1:
2: const numbers = [1, 2, 3];
3: numbers.map(num => num.toUpperCase()); // runtime error
4:
11. Array Type Safety (TS only)
1:
2: const ids: number[] = [1, 2, 3];
3: ids.push("4"); // Error
4:
1:
2: const ids = [1, 2, 3];
3: ids.push("4"); // JavaScriptЖ (mixed-type array)
4:
12. Immutable Readonly Arrays (TS only)
1:
2: const nums: readonly number[] = [1, 2, 3];
3: nums.push(4); // push doesn't exist on readonly array
4:
1:
2: // JavaScript array always mutable
3: const nums = [1, 2, 3];
4: nums.push(4); // Works
5:
Function:
13. Function Typing (TS only)
1:
2: function greet(name: string): string {
3: return `Hello, ${name}!`;
4: }
5:
14. Function Overloads (TS only)
1:
2: function pad(value: string, padding: number): string;
3: function pad(value: number, padding: string): number;
4: function pad(value: any, padding: any) { ... }
5:
1:
2: function pad(value, padding) { ... }
3:
Enums:
15. Enums (TS only)
1:
2: enum Status {
3: Active = 'ACTIVE',
4: Inactive = 'INACTIVE'
5: }
6:
1:
2: const Status = {
3: Active: 'ACTIVE',
4: Inactive: 'INACTIVE'
5: };
6:
16. Enum Reverse Mapping (TS only)
1:
2: // TypeScript (bi-directional enums)
3: enum Color { Red = 1 }
4: console.log(Color[1]); // ✅ "Red"
5:
1:
2: const Color = { Red: 1 };
3: console.log(Color[1]); // ❌ undefined (no auto-mapping)
4:
This:
17. Explicit this binding vs dynamic this
1:
2: function onClick(this: HTMLButtonElement) {
3: console.log(this.textContent);
4: }
5:
1:
2: function onClick() {
3: console.log(this.textContent); // Risky context
4: }
5:
Property:
18. Access Modifiers
1:
2: class Person {
3: public name: string; // accessible anywhere (default)
4: private age: number; // only accessible within class
5: protected id: string; // accessible within class and subclasses
6: readonly birthDate: Date; // can't be modified after initialization
7: }
8:
1:
2: class Person {
3: #age; // private field
4:
5: constructor(age) {
6: this.#age = age;
7: }
8: }
9:
19. Parameter Properties (TS only)
1:
2: class Person {
3: constructor(public name: string, private age: number) {
4: // automatically creates and assigns this.name and this.age
5: }
6: }
7:
20. Method Overloading (TS only)
1:
2: class Logger {
3: log(message: string): void;
4: log(message: string, level: number): void;
5: log(message: any, level?: any): void {
6: // Implementation
7: }
8: }
9:
1:
2: class Logger {
3: log(message, level) {
4: // no overloading, just multiple parameters
5: }
6: }
7:
21. Property Initialization (TS only)
1:
2: class Person {
3: name: string; // Error if strictPropertyInitialization is enabled
4:
5: constructor() {
6: this.name = "Default"; // Required initialization
7: }
8: }
9:
22. Property Declaration
1:
2: class Example {
3: prop: string; // Must declare first, requires explicit declaration
4: constructor() {
5: this.prop = "value";
6: }
7: }
8:
1:
2: class Example {
3: constructor() {
4: this.prop = "value"; // No declaration needed, property can add properties dynamically
5: }
6: }
7:
23. Autodeclaration variable in constructor
1:
2: class Point {
3: constructor(public x: number, public y: number) {}
4: // Auto-declares and assigns this.x and this.y
5: }
6:
1:
2: class Point {
3: constructor(x, y) { // must declare explicitly
4: this.x = x;
5: this.y = y;
6: }
7: }
8:
24. Property Accessors (Getters/Setters)
1:
2: class Person {
3: private _age: number;
4:
5: get age(): number {
6: return this._age;
7: }
8:
9: set age(value: number) {
10: if (value < 0) throw new Error("Age cannot be negative");
11: this._age = value;
12: }
13: }
14:
1:
2: class Person {
3: #age; // Private field
4:
5: get age() {
6: return this.#age;
7: }
8:
9: set age(value) {
10: if (value < 0) throw new Error("Age cannot be negative");
11: this.#age = value;
12: }
13: }
14:
25. Static Properties
1:
2: class MyClass {
3: static count: number = 0;
4: static increment(): void {
5: MyClass.count++;
6: }
7: }
8:
1:
2: class MyClass {
3: static count = 0;
4: static increment() {
5: MyClass.count++;
6: }
7: }
8:
26. Readonly Properties
1:
2: class Circle {
3: readonly PI = 3.14;
4: readonly radius: number;
5:
6: constructor(radius: number) {
7: this.radius = radius;
8: }
9: }
10:
1:
2: class Circle {
3: PI = 3.14;
4: constructor(radius) {
5: Object.defineProperty(this, 'radius', {
6: value: radius,
7: writable: false
8: });
9: }
10: }
11:
27. Optional and Mandatory Properties
1:
2: interface Config { url: string; timeout?: number }
3: const config: Config = { url: "/api" }; // timeout optional
4: const badConfig = { url: "/api", timeout: "1000" }; // timeout must be number
5:
1:
2: // JS runtime check
3: function createUser(user) {
4: if (!user.id) throw new Error("Missing required 'id'");
5: return { id: user.id, name: user.name || "Anonymous" };
6: }
7:
OR
1:
2: // JS define default value
3: function createUser({ id, name = "Anonymous" }) {
4: return { id, name };
5: }
6:
28. Index properties
1:
2: class StringArray {
3: [index: number]: string; // Explicit index signature
4:
5: constructor() {
6: this.data = {};
7: }
8:
9: setItem(index: number, value: string) {
10: this.data[index] = value; // OK
11: }
12:
13: getItem(index: number): string {
14: return this.data[index];
15: }
16: }
17:
18: const arr = new StringArray();
19: arr.setItem(0, "hello"); // ✅ Valid
20: arr.setItem(1, 123); // ❌ Error: Type 'number' is not assignable to type 'string'
21:
1:
2: class StringArray {
3: constructor() {
4: this.data = {};
5: }
6:
7: // JavaScript allows indexed access (but no type enforcement)
8: setItem(index, value) {
9: this.data[index] = value;
10: }
11:
12: getItem(index) {
13: return this.data[index];
14: }
15: }
16:
17: const arr = new StringArray();
18: arr.setItem(0, "hello");
19: console.log(arr.getItem(0)); // "hello"
20: arr.setItem(1, 123); // No error (JavaScript doesn't enforce types)
21:
Class inheritance:
29. Abstract Abstract Classes and Methods (TS only)
1:
2: abstract class Animal {
3: abstract makeSound(): void;
4:
5: move(): void {
6: console.log("Moving...");
7: }
8: }
9:
1:
2: //must use workarounds
3: class Animal {
4: makeSound() {
5: throw new Error("Abstract method not implemented");
6: }
7: }
8:
30. Inheritance and Overriding
1:
2: class Base {
3: greet(): void {
4: console.log("Hello!");
5: }
6: }
7: // override keyword and type checking
8: class Derived extends Base {
9: override greet(): void {
10: console.log("Hi!");
11: }
12: }
13:
1:
2: class Base {
3: greet() {
4: console.log("Hello!");
5: }
6: }
7: // no override checking
8: class Derived extends Base {
9: greet() { // No override keyword
10: console.log("Hi!");
11: }
12: }
13:
Interface:
31. Interface Implementation (TS only)
1:
2: interface Serializable {
3: serialize(): string;
4: }
5:
6: class MyClass implements Serializable {
7: serialize(): string {
8: return JSON.stringify(this);
9: }
10: }
11:
Generic:
32. Generic Classes (TS only)
1:
2: class Box<T> {
3: contents: T;
4: constructor(value: T) {
5: this.contents = value;
6: }
7: }
8:
1:
2: function echo<T>(value: T): T {
3: return value;
4: }
5: const result = echo<string>("Hello"); // Explicit type
6: const result2 = echo(123); // Inferred as number
7:
1:
2: function echo(value) {
3: return value;
4: }
5: const result = echo("Hello"); // Javascript - No type constraints
6:
Decorator:
33. Decorators (TS only)
1:
2: @sealed
3: class Greeter {
4: greeting: string;
5:
6: constructor(message: string) {
7: this.greeting = message;
8: }
9: }
10:
JavaScript (stage 3 proposal):
1:
2: @sealed
3: class Greeter {
4: @configurable(false)
5: greeting;
6: }
7:
Immutable Objects:
34. Immutable Objects
1:
2: const user = { name: "Alice" } as const;
3: user.name = "Bob"; // ❌ Error: readonly property
4:
1:
2: const user = { name: "Alice" };
3: user.name = "Bob"; // ✅ Javascript - Allowed
4:
Operators:
35. Keyof Operator (TS only)
1:
2: type Person = { name: string; age: number };
3: type PersonKeys = keyof Person; // "name" | "age"
4:
5: function getProperty(obj: Person, key: PersonKeys) {
6: return obj[key];
7: }
8:
1:
2: function getProperty(obj, key) {
3: if (key in obj) {
4: return obj[key];
5: }
6: throw new Error("Invalid key");
7: }
8:
OR
1:
2: function getProperty<T, K extends keyof T>(obj: T, key: K) {
3: return obj[key]; // 100% type-safe
4: }
5: getProperty({ name: "Alice" }, "name"); // ✅
6: getProperty({ name: "Alice" }, "age"); // ❌ Error
7:
1:
2: function getProperty(obj, key) {
3: return obj[key]; // No safety
4: }
5: getProperty({ name: "Alice" }, "age"); // ❌ Returns undefined (silent failure)
6:
36. Optional Chaining (?.) vs TypeScript's Optional Properties
1:
2: type User = {
3: name: string;
4: address?: { // Optional property
5: city: string;
6: }
7: };
8:
9: const user: User = { name: 'Alice' };
10: const city = user.address?.city; // TS understands optional chains
11:
1:
2: const user = { name: 'Alice' };
3: const city = user.address?.city; // Works in modern JS, but no type checking
4:
37. Non-Null Assertion Operator (!)
1:
2: const element = document.getElementById('root')!; // No null-check needed
3: element.innerHTML = 'Hello'; // Safe (according to TS)
4:
1:
2: const element = document.getElementById('root');
3: if (element) { // Required in JS
4: element.innerHTML = 'Hello';
5: }
6:
38. Strict Null Checks (TS only)
1:
2: // TypeScript (with strictNullChecks)
3: let name: string;
4: console.log(name.length); // Error: 'name' is possibly undefined
5:
1:
2: let name;
3: console.log(name.length); // // JavaScript Runtime error: Cannot read property 'length' of undefined
4:
Type manipulation:
39. Type Aliases (TS only)
1:
2: class StringArray {
3: [index: number]: string; // Explicit index signature
4:
5: constructor() {
6: // TypeScript
7: type User = {
8: id: string | number;
9: name: string;
10: };
11:
1:
2: // JavaScript JSDoc
3: /**
4: * @typedef {Object} User
5: * @property {string | number} id
6: * @property {string} name
7: */
8:
40. Union Types (TS only)
1:
2: let result: string | number;
3:
41. Intersection Types (TS only)
1:
2: type Admin = User & { permissions: string[] };
3:
42. Type Assertions (TS only)
1:
2: const element = document.getElementById('root') as HTMLElement;
3:
OR
1:
2: const input = <HTMLInputElement>document.getElementById('input');
3:
43. Utility Types (Partial<T>, Pick<T, K>) (TS only)
1:
2: type User = {
3: id: number;
4: name: string;
5: email: string;
6: };
7:
8: // Partial<T> - Makes all properties optional
9: type PartialUser = Partial<User>;
10: /* Equivalent to:
11: { id?: number; name?: string; email?: string } */
12:
13: // Pick<T, K> - Select specific properties
14: type UserNameOnly = Pick<User, 'name'>; // { name: string }
15:
44. Conditional Types (T extends U ? X : Y) (TS only)
1:
2: type IsString<T> = T extends string ? true : false;
3:
4: type A = IsString<"hello">; // true
5: type B = IsString<123>; // false
6:
45. Branded Types (nominal typing) (TS only)
1:
2: type UserID = string & { __brand: "UserID" };
3: function createUser(id: UserID) { ... }
4:
1:
2: function createUser(id) { ... } // Any string can pass
3:
1:
2: type Meters = number & { __brand: "Meters" };
3: type Seconds = number & { __brand: "Seconds" };
4:
1:
2: // Example: Add an invisible "sticker" to the type
3: type UserID = string & { __brand: "UserID" };
4: type OrderID = string & { __brand: "OrderID" };
5:
6: // Helper function to apply the "sticker"
7: function createUserID(id: string): UserID {
8: return id as UserID; // Trust me, this is a UserID
9: }
10:
11: // Usage
12: const userId = createUserID("user_123"); // ✅ Properly branded
13: const orderId = "order_456" as OrderID; // ✅ (alternative syntax)
14:
15: function processUser(id: UserID) {...}
16:
17: processUser(userId); // ✅ Works
18: processUser(orderId); // ❌ Error: Not a UserID!
19:
Execute TS:
Browser can execute only JS, but Vite server or WebPack can automatically transform TS to JS :
<script lang="ts">
...
</script>
| Vite | Webpack (ts-loader) | Webpack (babel-loader) | |
|---|---|---|---|
| Speed | ⚡ Fastest (esbuild) | 🐢 Slow (full TS compilation) | ⚡ Fast (Babel) |
| Type Checking | ❌ No (unless vite-plugin-checker) | ✅ Yes | ❌ No |
| Zero Config | ✅ Yes | ❌ No | ❌ No |
| HMR (Hot module reload) | ✅ Excellent | ✅ Good | ✅ Good |
| Advanced TS Features: | ⚠ May need plugins | ✅ Full support | ⚠ Some limitations |
| Decorators (@Component) | ⚠ Needs config | ✅ Yes | ⚠ With plugin |
| Const Enums | ✅ Yes | ✅ Yes | ❌ No (converted) |
| Namespaces | ✅ Yes | ✅ Yes | ⚠ Limited |
| Custom JSX Factories | ✅ Yes | ✅ Yes | ⚠ Needs plugin |
| emitDecoratorMetadata | ❌ No | ✅ Yes | ❌ No |
| Satisfies Operator | ✅ Yes | ✅ Yes | ✅ Yes (Babel 7.21+) |
| Template Literal Types | ✅ Yes | ✅ Yes | ❌ Stripped |
| Best For | Modern projects, quick start | Strict type checking needed | Existing Babel setups, speed focus |
AngularTypesctiptLearning context:
Comments (
)
)
Link to this page:
http://www.vb-net.com/TypescriptLearningStartPoint/JsTsDifference.htm
|
|