Functions Flashcards

1
Q

What are function type expressions and how do you use them in TypeScript?

A

Function type expressions are similar to arrow functions, defining the parameter types and return type.

// Basic function type expression
type GreetFunction = (name: string) => string;
const greet: GreetFunction = (name) => `Hello, ${name}`;

// Multiple parameters
type MathOperation = (x: number, y: number) => number;
const add: MathOperation = (a, b) => a + b;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What are call signatures and how do they differ from type expressions?

A

Call signatures allow you to add properties to functions using object type syntax.

interface DescribableFunction {
    description: string;
    (someArg: number): boolean;
};

function doSomething(fn: DescribableFunction) {
    console.log(fn.description);
    console.log(fn(6));
}

// Implementation
const myFunc: DescribableFunction = (n: number) => n > 5;
myFunc.description = "Checks if number is greater than 5";
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are construct signatures and when would you use them?

A

Construct signatures define types that can be instantiated with ‘new’.

type SomeConstructor = {
    new (s: string): object;
};

class Example {
    constructor(s: string) {
        console.log(s);
    }
}

function fn(ctor: SomeConstructor) {
    return new ctor("hello");
}

// With both call and construct signatures
interface CallAndConstruct {
    new (s: string): Date;
    (n?: number): Date;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

How do you write and use generic functions?

A

Generic functions allow you to work with multiple types while maintaining type safety.

function identity<T>(arg: T): T {
    return arg;
}

// Using arrow functions
const identity2 = <T>(arg: T): T => arg;

// Generic with constraints
function firstItem<T>(arr: T[]): T | undefined {
    return arr[0];
}

// Multiple type parameters
function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How does type inference work with generics?

A

TypeScript can often infer generic types from usage context.

function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
    return arr.map(func);
}

// Type inference in action
const numbers = [1, 2, 3];
const doubled = map(numbers, n => n * 2);  // TypeScript infers number[]

const strings = ["hello", "world"];
const lengths = map(strings, s => s.length);  // TypeScript infers number[]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you use constraints with generic types?

A

Constraints limit what types can be used with generics using ‘extends’.

interface Lengthwise {
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// Valid
logLength("hello");
logLength([1, 2, 3]);
logLength({ length: 10, value: 3 });

// Invalid - number doesn't have length
// logLength(42); // Error!
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

How do you work effectively with constrained types?

A

You can access properties guaranteed by constraints.

function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
    return obj[key];
}

let obj = { a: 1, b: 2, c: 3 };

// Valid
getProperty(obj, "a");
// Invalid
// getProperty(obj, "z"); // Error: "z" is not in keyof Type
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

When do you need to specify type arguments explicitly?

A

Sometimes TypeScript needs help inferring types.

function create<T>(value: T): T[] {
    return [value];
}

// Explicit type argument
const stringArray = create<string>("hello");

// Complex example
function combine<T>(arr1: T[], arr2: T[]): T[] {
    return [...arr1, ...arr2];
}

// Need explicit type here
const mixed = combine<string | number>([1, 2], ["a", "b"]);
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How do you work with optional parameters?

A

Optional parameters are marked with ? and must come after required parameters.

function buildName(firstName: string, lastName?: string): string {
    if (lastName) {
        return `${firstName} ${lastName}`;
    }
    return firstName;
}

// Default parameters
function greet(name = "World"): string {
    return `Hello, ${name}!`;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How do you implement function overloads?

A

Function overloads allow multiple call signatures for a single function.

```typescript
function makeDate(timestamp: number): Date;
function makeDate(year: number, month: number, day: number): Date;
function makeDate(yearOrTimestamp: number, month?: number, day?: number): Date {
if (month !== undefined && day !== undefined) {
return new Date(yearOrTimestamp, month - 1, day);
}
return new Date(yearOrTimestamp);
}

// Usage
const d1 = makeDate(123456789);
const d2 = makeDate(2024, 1, 1);
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How do you work with the object type in TypeScript?

A

The object type represents any non-primitive type.

```typescript
const obj: object = { x: 10, y: 20 };
// obj.x; // Error: Property ‘x’ does not exist on type ‘object’

// Better to use specific type
const point: { x: number; y: number } = { x: 10, y: 20 };
point.x; // OK
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the unknown type and how is it used safely?

A

unknown represents any value but requires checking before use.

```typescript
function processValue(val: unknown): string {
if (typeof val === “string”) {
return val.toUpperCase();
}
if (typeof val === “number”) {
return val.toFixed(2);
}
throw new Error(“Invalid type”);
}

// Usage
let value: unknown = “hello”;
// value.toUpperCase(); // Error
if (typeof value === “string”) {
value.toUpperCase(); // OK
}
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is the never type and when is it used?

A

never represents values that never occur.

```typescript
function error(message: string): never {
throw new Error(message);
}

function infiniteLoop(): never {
while (true) {}
}

// Exhaustive checking
type Shape = Circle | Square;
function assertNever(x: never): never {
throw new Error(“Unexpected object: “ + x);
}
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How do you work with rest parameters and spread arguments?

A

Rest parameters collect multiple arguments into an array.

```typescript
// Rest parameters
function sum(…numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}

// Rest arguments
const numbers = [1, 2, 3];
console.log(sum(…numbers));

// Typing tuple rest parameters
function concat<T extends unknown[]>(…arrays: T[]): T[number][] {
return arrays.flat();
}
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How do you use parameter destructuring with TypeScript?

A

Parameter destructuring lets you unpack objects or arrays in parameters.

```typescript
interface User {
name: string;
age: number;
}

function printUser({ name, age }: User) {
console.log(${name} is ${age} years old);
}

// With defaults
function printUserWithDefaults({ name = “Anonymous”, age = 0 }: Partial<User> = {}) {
console.log(`${name} is ${age} years old`);
}
~~~</User>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What is the void return type and how does it work?

A

void indicates a function doesn’t return a value.

```typescript
function logMessage(msg: string): void {
console.log(msg);
}

// void vs undefined
function returnsVoid(): void {
return undefined; // OK
}

function returnsUndefined(): undefined {
return undefined; // OK
}

// Contextual typing with void
type VoidFunc = () => void;

const f1: VoidFunc = () => true; // OK - return value is ignored
~~~