typescript | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / typescript

typescript

maintained by mgd34msu

star 3 account_tree 0 verified_user MIT License
bolt View GitHub

name: typescript description: Adds static typing to JavaScript with TypeScript including type annotations, interfaces, generics, and advanced type utilities. Use when setting up TypeScript projects, defining types, creating generic utilities, or debugging type errors.

TypeScript

Strongly typed programming language that builds on JavaScript, providing type safety and improved developer experience.

Quick Start

Initialize in existing project:

npm install -D typescript
npx tsc --init

Create React project with TypeScript:

npm create vite@latest my-app -- --template react-ts

Key tsconfig.json options:

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "include": ["src"]
}

Basic Types

Primitives

// String
let name: string = 'Alice';

// Number
let age: number = 30;
let price: number = 19.99;

// Boolean
let isActive: boolean = true;

// Null and Undefined
let nothing: null = null;
let notDefined: undefined = undefined;

// Symbol
let id: symbol = Symbol('id');

// BigInt
let bigNumber: bigint = 100n;

Arrays

// Array of strings
let names: string[] = ['Alice', 'Bob'];

// Alternative syntax
let numbers: Array<number> = [1, 2, 3];

// Tuple (fixed length, specific types)
let tuple: [string, number] = ['Alice', 30];

// Readonly array
let readonlyArr: readonly number[] = [1, 2, 3];

Objects

// Inline object type
let user: { name: string; age: number } = {
  name: 'Alice',
  age: 30,
};

// Optional properties
let config: { host: string; port?: number } = {
  host: 'localhost',
};

// Index signature
let dictionary: { [key: string]: number } = {
  one: 1,
  two: 2,
};

Type Aliases and Interfaces

Type Aliases

// Object type
type User = {
  id: string;
  name: string;
  email: string;
};

// Union type
type Status = 'pending' | 'active' | 'completed';

// Intersection type
type Admin = User & {
  role: 'admin';
  permissions: string[];
};

// Function type
type Callback = (error: Error | null, result: string) => void;

Interfaces

interface User {
  id: string;
  name: string;
  email: string;
}

// Extending interfaces
interface Admin extends User {
  role: 'admin';
  permissions: string[];
}

// Declaration merging (interfaces only)
interface User {
  age?: number; // Adds to existing User interface
}

// Implementing interfaces
class UserService implements User {
  id = '1';
  name = 'Alice';
  email = 'alice@example.com';
}

When to Use Which

Feature Type Interface
Object shapes Both Both
Union/Intersection Yes No (use extends)
Primitives Yes No
Declaration merging No Yes
Class implements Both Both

Rule of thumb: Use interface for public APIs (mergeable), type for complex types.

Union and Intersection Types

Union Types

type Result = string | number;
type Status = 'pending' | 'success' | 'error';

function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

Intersection Types

type HasId = { id: string };
type HasTimestamp = { createdAt: Date; updatedAt: Date };

type Entity = HasId & HasTimestamp;

const entity: Entity = {
  id: '1',
  createdAt: new Date(),
  updatedAt: new Date(),
};

Discriminated Unions

type Success = {
  status: 'success';
  data: string;
};

type Error = {
  status: 'error';
  error: string;
};

type Result = Success | Error;

function handleResult(result: Result) {
  switch (result.status) {
    case 'success':
      console.log(result.data); // TypeScript knows data exists
      break;
    case 'error':
      console.log(result.error); // TypeScript knows error exists
      break;
  }
}

Functions

Basic Functions

// Parameter and return types
function greet(name: string): string {
  return `Hello, ${name}!`;
}

// Arrow function
const add = (a: number, b: number): number => a + b;

// Optional parameters
function greet(name: string, greeting?: string): string {
  return `${greeting ?? 'Hello'}, ${name}!`;
}

// Default parameters
function greet(name: string, greeting = 'Hello'): string {
  return `${greeting}, ${name}!`;
}

// Rest parameters
function sum(...numbers: number[]): number {
  return numbers.reduce((a, b) => a + b, 0);
}

Function Overloads

function parse(value: string): number;
function parse(value: number): string;
function parse(value: string | number): string | number {
  if (typeof value === 'string') {
    return parseInt(value, 10);
  }
  return value.toString();
}

const num = parse('123'); // number
const str = parse(123);    // string

Async Functions

async function fetchUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

// With error handling
async function fetchUser(id: string): Promise<User | null> {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) return null;
    return response.json();
  } catch {
    return null;
  }
}

Generics

Generic Functions

// Basic generic
function identity<T>(value: T): T {
  return value;
}

const num = identity(42);      // number
const str = identity('hello'); // string

// Multiple type parameters
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

// Constrained generic
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: 'Alice', age: 30 };
const name = getProperty(user, 'name'); // string

Generic Interfaces

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

interface PaginatedResponse<T> {
  items: T[];
  page: number;
  pageSize: number;
  total: number;
}

const usersResponse: PaginatedResponse<User> = {
  items: [],
  page: 1,
  pageSize: 10,
  total: 0,
};

Generic Classes

class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);

Utility Types

Built-in Utilities

interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

// Partial - all properties optional
type PartialUser = Partial<User>;

// Required - all properties required
type RequiredUser = Required<User>;

// Pick - select specific properties
type UserPreview = Pick<User, 'id' | 'name'>;

// Omit - exclude specific properties
type UserWithoutId = Omit<User, 'id'>;

// Readonly - all properties readonly
type ReadonlyUser = Readonly<User>;

// Record - object with specific key/value types
type UserRoles = Record<string, User>;

// Extract - extract union members
type AdminRole = Extract<User['role'], 'admin'>; // 'admin'

// Exclude - exclude union members
type NonAdminRole = Exclude<User['role'], 'admin'>; // 'user'

// NonNullable - remove null and undefined
type NonNullString = NonNullable<string | null>; // string

// ReturnType - get function return type
type FetchReturn = ReturnType<typeof fetch>; // Promise<Response>

// Parameters - get function parameter types
type FetchParams = Parameters<typeof fetch>; // [input: RequestInfo, init?: RequestInit]

Custom Utility Types

// Make specific properties optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

type UserWithOptionalEmail = PartialBy<User, 'email'>;

// Make specific properties required
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

// Deep partial
type DeepPartial<T> = T extends object
  ? { [P in keyof T]?: DeepPartial<T[P]> }
  : T;

// Deep readonly
type DeepReadonly<T> = T extends object
  ? { readonly [P in keyof T]: DeepReadonly<T[P]> }
  : T;

Type Guards

typeof Guards

function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.toUpperCase(); // value is string
  }
  return value.toFixed(2); // value is number
}

instanceof Guards

function handleError(error: Error | string) {
  if (error instanceof Error) {
    console.log(error.message);
  } else {
    console.log(error);
  }
}

in Guards

interface Dog {
  bark(): void;
}

interface Cat {
  meow(): void;
}

function speak(animal: Dog | Cat) {
  if ('bark' in animal) {
    animal.bark();
  } else {
    animal.meow();
  }
}

Custom Type Guards

interface User {
  type: 'user';
  name: string;
}

interface Admin {
  type: 'admin';
  name: string;
  permissions: string[];
}

function isAdmin(person: User | Admin): person is Admin {
  return person.type === 'admin';
}

function greet(person: User | Admin) {
  if (isAdmin(person)) {
    console.log(`Admin ${person.name} with permissions: ${person.permissions}`);
  } else {
    console.log(`User ${person.name}`);
  }
}

Mapped Types

// Make all properties nullable
type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};

// Add prefix to property names
type Prefixed<T, Prefix extends string> = {
  [P in keyof T as `${Prefix}${string & P}`]: T[P];
};

// Filter properties by type
type StringProperties<T> = {
  [P in keyof T as T[P] extends string ? P : never]: T[P];
};

Conditional Types

// Basic conditional
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

// Infer keyword
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type FnReturn = GetReturnType<() => string>; // string

// Distributive conditional types
type ToArray<T> = T extends any ? T[] : never;

type StrOrNumArray = ToArray<string | number>; // string[] | number[]

// Flatten array type
type Flatten<T> = T extends Array<infer U> ? U : T;

type Str = Flatten<string[]>;  // string
type Num = Flatten<number>;    // number

React Types

import { ReactNode, FC, ComponentProps, PropsWithChildren } from 'react';

// Props with children
interface CardProps {
  title: string;
  children: ReactNode;
}

// Using PropsWithChildren
type ButtonProps = PropsWithChildren<{
  onClick: () => void;
  variant?: 'primary' | 'secondary';
}>;

// Get props from component
type InputProps = ComponentProps<'input'>;
type DivProps = ComponentProps<'div'>;

// Extend HTML element props
interface ButtonProps extends ComponentProps<'button'> {
  variant?: 'primary' | 'secondary';
}

// Event types
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {};

Best Practices

  1. Enable strict mode - Catch more errors at compile time
  2. Prefer interfaces for objects - Better error messages, extensible
  3. Use type for unions - Type aliases handle unions better
  4. Avoid any - Use unknown for truly unknown types
  5. Leverage inference - Don't over-annotate obvious types
  6. Use const assertions - as const for literal types

Common Mistakes

Mistake Fix
Using any everywhere Use unknown or proper types
Not enabling strict mode Set "strict": true
Ignoring type errors Fix them or use proper assertions
Over-typing Let TypeScript infer when obvious
Not using generics Add type parameters for reusability

Reference Files

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 3
GitHub Forks 0
Created Jan 2026
Last Updated il y a 5 mois
tools tools ide plugins

Related Skills

writing-skills
chevron_right
codex
chevron_right
smart-illustrator
chevron_right
ast-index
chevron_right
packmind-standard-creator
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.