TypeScript Flashcards

1
Q

In dynamically typed languages, a variable’s type is determined when?

A

At runtime, based on the type of value it is assigned.

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

In statically typed languages, each variable must be assigned a specific data type when it is declared, and functions must specify the type of value they return.

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

In TypeScript, compile-time errors occur during…

A

the process of converting the TypeScript code into JavaScript code.

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

runtime errors occur in JavaScript when…

A

the code is being executed

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

The TypeScript compiler can detect both ____ and ____ before the code is executed.

A

syntax and type errors

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

What is type safety?

A

Type safety ensures that values in your code are used in a manner consistent with their declared types, helping catch potential errors at compile time rather than at runtime.

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

Changing existing JavaScript programs to TypeScript programs won’t “break” them, they will still compile and run. However, the TypeScript compiler will now throw a variety of helpful warnings and errors at build time, which we can resolve by updating our code and adding type annotations.

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

What are type annotations?

A

Type annotations are used to explicitly specify the type of the variable:

let myName: string = "Alice";

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

What will be logged to the console and why? How can we prevent this behavior?
let numbers: Array<number> = [1, 2, 3, 4, 5];
let myNum: number = numbers[5];
console.log(myNum);

A

In the above code, we are able to assign the value undefined to the variable myNum, even though myNum has the type number. This seems like a bug, but TypeScript doesn’t raise a warning.

The issue is that TypeScript can’t know how long the array is, or will be. In other words, because JavaScript arrays have a dynamic length, the TypeScript compiler doesn’t know whether any particular index is out of bounds. As a result, it infers that any elements returned from the array are of the type the array contains.

You can add code to check if the variable is undefined. Or you can use the noUncheckedIndexedAccess compiler option in TypeScript.

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

What is the noUncheckedIndexedAccess compiler option?

A

The noUncheckedInexedAccess option is used to improve type safety by ensuring that all indexed access to object properties is properly checked. When this option is enabled, TypeScript treats every object property access using an index as potentially undefined, unless the type system can definitively determine that the property exists.

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

Tuples can be very useful in TypeScript when you want to…

A

work with a collection of values that have a specific order and data type.

let aTuple: [string, number, boolean] = ["Launch School", 1, true];

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

Primary differences between arrays and tuples?

A

Tuples have a fixed length.
You cannot access an out-of-bounds index of a tuple.

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

What happens if you call .push() or .pop() on a tuple? Why?

A

As long as you are pushing a valid type for the tuple, the TypeScript compiler will not raise an error. The problem is that tuples are just arrays, and thus they have all of the methods that arrays have. For this reason, it is generally considered a best practice to avoid using methods like push() and pop() when working with tuples as this can lead to unexpected behaviors.

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

This array consists of both string and boolean values. If you had to assign a type definition to myArray, what would it be?

const myArray = ["is", "launch school", "awesome", true, "or", false];

A

const myArray: (string | boolean)[] = [ "is", "launch school", "awesome", true, "or", false, ];

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

____ is used as the return type for functions that don’t return a value.

A

void

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

What is type inference?

A

Type inference is a feature in TypeScript that allows the compiler to automatically deduce the types of variables when they are not explicitly specified.

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

What is meant by a method/function signature?

A

In TypeScript, a method signature (or function signature) defines:

1) the name of a method
2) the number and types of its parameters
3) the type of its return value.

It specifies how a method can be called, what arguments it takes, and what it returns, without providing the method’s implementation.

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

void represents…

A

the absence of a value

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

Values with the void type cannot be…

A

1) assigned to any other data type
const result: void = greet("Jane");
const myUndefined: undefined = result; // Type 'void' is not assignable to type 'undefined'

2) cannot be used in a conditional to test truthiness.
const myBool: boolean = result ? true : false; // An expression of type 'void' cannot be tested for truthiness.

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

Why does TypeScript raise an error with the following code?

function logSum(a: number, b: number): void { const sum = a + b; console.log("The sum of", a, "and", b, "is", sum); return sum; }

logSum(3, 4);

A

Because a function with a return type of void is intended to not return a value and sum is returned. If a function’s return type is void and it has an explicit return it should only return undefined, otherwise TypeScript will raise an error.

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

What is a literal type? List some specific examples.

A

In TypeScript literal types are used to describe the literal values that a variable can have.

Specific examples are string literals, numeric literals, and boolean literals.

let five: 5 = 5;
let hasName: true = true;

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

What is any?

A

any is a special TypeScript type that represents any possible value.

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

In TypeScript, type errors happen at…

A

compile-time

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

What is the following an example of?

type Person = { name: string; age: number };

A

The code snippet is an example of type aliasing.

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

What is type aliasing?

A

Type aliasing is when we define new custom types based on existing type using the type keyword.

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

What is meant by an object’s shape?

A

The “shape” of an object refers to the structure of its properties and their types. When we talk about the shape of an object, we are referring to the names and types of the object’s properties.

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

In TypeScript’s structural typing rules, if we have two types, TypeA and TypeB, then TypeB is assignable to TypeA if…

type TypeA = { name: string; age: number };
type TypeB = { name: string; age: number; gpa: number };

A

it has at least the same members (properties and property types) as TypeA.

In other words, TypeB can have additional properties that aren’t available on TypeA, but as long as it has the same properties and associated value types as TypeA, then it is assignable.

*the exception to this rules is with object literals
type Employee = { name: string; age: number };
const jane: Employee = { name: "Jane Smith", age: 30, gpa: 4.0 }; // Type '{ name: string; age: number; gpa: number; }' is not assignable to type 'Employee'.
// Object literal may only specify known properties, and 'gpa' does not exist in type 'Employee'.

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

In TypeScript, readonly properties are used to create properties that…

A

can only be set once during initialization and cannot be modified afterward. Once the value of a readonly property is set, it cannot be changed throughout the object’s lifetime.

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

Object.freeze()

A

Takes an object as an argument and freezes it. This prevents the object from being mutated. Any attempts to mutate the object will throw an error at runtime.

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

What are the characteristics of a ReadonlyArray?

A

In TypeScript ReadonlyArray’s cannot be mutated and do not have the typical array methods available to mutate them such as pop, push, and shift.

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

Although developers coming from a JavaScript background tend to skip adding readonly to the properties of their types, we would encourage you to think carefully about whether each property’s value should change over the course of a program’s execution. If not, adding readonly will help you uncover and prevent serious issues later on.

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

What is the purpose of implements?

A

In TypeScript, the implements keyword is used to ensure that a class adheres to the contract defined by an interface. When a class implements an interface, it must provide concrete implementations for all the properties and methods defined in the interface.

Think of implements as a contract between the class definition and the interface. In order to fulfill the contract, you have to explicitly add the correct type information to the properties and methods.

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

What is private?

A

The keyword private is used to control the visibility of properties and methods within a class hierarchy.

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

What is a union type?

A

A union type is a type formed from two or more other types, representing values that may be any one of those types. We refer to each of these types as the union’s members.

union types in TypeScript allow us to define a type that can hold more than one type

let unionDemo: (number | string) = 'hello';

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

TypeScript uses a structural typing system. This means…

A

TypeScript enforces type safety based on the shape of the types rather than their explicit declarations.

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

What is a type assertion?

A

Type assertion in TypeScript is a mechanism that allows you to override the inferred type of an expression and specify a different type that you know to be correct. It doesn’t perform any type checking or restructuring of data; it simply tells the TypeScript compiler to treat a value as a particular type. Type assertions are useful when you have more information about the type of a value than TypeScript can infer on its own.

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

What is a type predicate?

A

A type predicates is a special return value that allow a developer to create custom type guards.

To define a type predicate we simply define a function whose return type is a type predicate (syntax:[parameterName] is [type]). When the function returns a truthy value, the TypeScript compiler will determine that the specified argument is of the given type.

the TypeScript compiler does not verify the logic within your type predicate function correctly determines the specified type

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

What are the five type guards?

A

typeof
in
truthiness
instanceof

type predicates (custom type guards)

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

What is a discriminant property?

A

A discriminant property is a common property for all members of a union with a unique literal value for each type in a union. A common practice is for the discriminant property value to be the name of the type in lowercase.

40
Q

What is narrowing?

A

Narrowing is the process of refining a value from a larger set of possible types to a smaller set of possible types. Using narrowing TypeScript can deduce a more specific type for a value based on the structure of the code.

40
Q

Can you explain why the following code does not contain any type errors?

function getFirstThree(x: number[] | string) {
  return x.slice(0, 3);
}
A

When working with union types in TypeScript, you may only perform an operation (without narrowing) if the operation is valid for all members of the union. Because arrays and strings both have a .slice method there is no type error and no narrowing is required.

41
Q

What does assignability refer to?

A

In TypeScript assignability refers to the process of determining whether a value of one type can be assigned to a variable or parameter of another type.

42
Q

How do narrow and wide types differ?

A

A narrow type refers to a type that is more specific and represents a smaller set of possible values. A wide type is more general and represents a larger set of possible values.

43
Q

When working with union types, how does TypeScript determine if an operation is valid?

A

When working with union types, TypeScript will only allow an operation if it is valid for every member of the union.

Note that when working with objects, this means that TypeScript will only allow us to access properties that are available on all of the objects.

44
Q

How does TypeScript infer the return type of a function?

A

In TypeScript, the return type of a function is inferred based on all possible return paths within the function. When a function can return different types depending on conditions, TypeScript infers the return type to be a union of all those possible types. This ensures that the function signature accurately represents all potential outputs, providing a comprehensive type safety.

45
Q

What is a function overload?

A

Function overloads provide a way for the developer to express the relationship between an argument type and return type when a function takes many types of arguments.

46
Q

Function overloads are composed of…

A

Two or more overload function signatures and an implementation signature.

47
Q

What is an overload signature? What is required for an overload signature to be compatible?

A

Overload signatures are used to define the multiple variations of a function’s signature. This allows the function to accept parameters of varying types and return different types based on those parameters.

For an overload signature to be compatible:
1) Each parameter in an overload signature should have a corresponding parameter in the implementation signature.

2) The overload parameter type should be assignable to the implementation parameter type.

3) The overload return type should be assignable to the implementation return type.

48
Q

What must we be cautious of when using function overloads?

A

When using function overloads the TypeScript compiler ensures that the overload signatures are compatible with the implementation signature.

TypeScript does not validate that the function’s implementation correctly implements the overload signatures.

49
Q

Generics can be though of as…

A

all-purpose placeholders for a type that can be specified later.

50
Q

The following is an example of a…

type User<T> = {
  name: string;
  age: T;
};
A

Generic object

51
Q

The following is an example of a…

function first<T>(arr: T[]): T {
  return arr[0];
}
A

Generic function.

52
Q

The following is an example of a…

const numsAndStrings: Array<string | number> = [1, "2"];
A

Generic Array.

We could also use the syntax….
~~~
const numsAndStrings: (string | number)[] = [1, ‘2’];
~~~

53
Q

Why is narrowing important?

A

Narrowing is necessary when a function is generic or accepts a wide set of possible types. Because the TypeScript compiler’s default behavior is to only allow access to properties/methods that are common between members of a given type unless we narrow a value’s type sufficiently so the TypeScript compiler determines we can safely access those properties/methods.

54
Q

In TypeScript we can use the in operator to narrow down an object based on…

A

its unique properties.

55
Q

What is a discriminated union?

A

A discriminated union is a narrowing technique where a common discriminant property is added to each member of a union. This property can then be used to differentiate between the members of the union.

56
Q

What are some benefits of using discriminated unions?

A

One benefit is that with the creation of a discriminant property to express the unique types is very explicit in the code. Another benefit is that when working with more complex objects you don’t need to comb through the shapes of all the union types to determine which properties could be used to narrow with the in operator.

57
Q

What is exhaustiveness checking?

A

Exhaustiveness checking is a feature in TypeScript that is used to ensure that all possible values of a discriminated union are handled in control flow constructs such as switch statements and if/else chains.

58
Q

What is never?

A

never is a special type is TypeScript. Assigning any value to a variable of type never will lead to a type error.

59
Q

How is exhaustiveness checking implemented?

A

Exhaustiveness checking is most commonly implemented within a conditional path that should never be reached using a combination of TypeScript’s never type and JavaScript runtime errors.

const _exhaustiveCheck: never = animal;
return Unknown animal: ${JSON.stringify(_exhaustiveCheck)};

60
Q

Describe the assignability for a variable of type any.

A

All types are assignable to a variable of type any and a value of type any can be assigned to every other type (except never).

61
Q

Using ____ essentially turns off type checking for a given value or assignment. This can lead to ____ ____, where TypeScript’s type system fails to catch a type error.

A

the type any

type unsoundness

62
Q

When might it be appropriate to use any?

A

1) when using 3rd party libraries that do not have TypeScript type definitions (or they are incomplete/inaccurate).

2) when migrating to TypeScript from vanilla JavaScript gradually.

63
Q

What is the default type of function parameters if not specified?

A

any

64
Q

What is type unsoundness?

A

Type unsoundness is when the type system fails to prevent type errors, resulting in runtime errors and bugs.

65
Q

What are three common sources of type unsoundness mentioned in the curriculum?

A

1) any as it essentially turns off type checking.
2) Incorrect type assertions
3) Accessing out-of-bounds index of an array.

66
Q

What are the characteristics of the type unknown?

A

unknown is a type in TypeScript that is similar to any in that any type may be assigned to it. However unknown is safer than any in that it is not assignable to any other type and you cannot perform any actions on it without first narrowing its type.

67
Q

What is declaration merging?

A

Declaration merging refers to TypeScript’s ability to take two separate interface declarations that share the same name and create a single interface that merges the original ones.

Declaration merging combines the properties and methods from both declarations into one.

68
Q

When declaration merging…If two declarations define the same member they must …

A

have the same type. Otherwise TypeScript will throw a type error.

69
Q

How is extends used with interfaces?

A

It essentially allows you to use an existing type as a base when defining a new type. When extends is used with an interface it creates a new interface that includes all the properties of one or more existing interfaces.

70
Q

Can you use extend with type?

A

The extends keyword only works with interface definitions, not type definitions. However a interface can extend a type.

71
Q

If you are extending an interface with another interface that has the same property…

A

the new property’s type must be assignable to the existing property type.

72
Q

What is the role of the & operator?

A

The & operator is used to create a type intersection, a new type with the properties and methods of multiple types.

73
Q

What happens if you create a type intersection with conflicting properties (no intersection between identical property types)?

A

If you create a type intersection with conflicting properties, TypeScript will not immediately inform the developer by throwing a type error. Instead the property will be given the type never and only when you try to define a new value with the intersection type will a type error be thrown. This behavior makes type intersections less desirable to extending interfaces.

74
Q

What is an interface?

A

An interface defines the shape of an object.

75
Q

Index signatures are used to…

A

define a dynamic set of properties for an object.

76
Q

The following is demonstrating the use of…
~~~
interface Accounts {
[key: string]: string;
}
~~~

Describe the code.

A

Index signatures.

Accounts is an interface with an index signature that allows any string key and the value type to be a string.

77
Q

When adding named properties to an object type that utilizes index signatures, the named properties must have types that are…

A

assignable to the type in the index signature.

78
Q
interface StringArray {
  [index: number]: string;
}

Above, we have a StringArray interface which has an index signature. This index signature states that when a StringArray is indexed with a number, it will return a string.

A
79
Q

What is the proper syntax for utilizing an index signature?

A

{ [key: TYPE]: TYPE }

When indexed with TYPE it will return a value of TYPE

80
Q

What is keyof?

A

keyof is a TypeScript operator that evaluates to a union of an interface’s properties. It is very useful for dynamically creating a new type based on the properties of an existing interface.

81
Q

What is the syntax for defining a generic (function) constraint?

A

A generic constraint is defined using the extends keyword.

Here are two examples:

function anotherFunc<T extends { age: number }>

function someFunc<T, K extends keyof T>

82
Q

What is the ?? operator?

A

The ?? is the nullish coalescing operator. This operator checks if the value on the left-hand side is nullish (either null or undefined), and if it is, it returns the value on the right-hand side.

83
Q

The options parameter pattern in TypeScript allows us to pack optional parameters into a single options object, which simplifies the function signature and makes it easier to add or remove optional parameters in the future. Optional object properties are automatically unioned with undefined, which means that they can be absent from the object. Finally, we can use the nullish coalescing operator (??) to provide default values for these properties.

A
interface RectangleOptions {
  unit?: string;
}

function calculateRectangleArea(
  width: number,
  height: number,
  options: RectangleOptions = {}
): string {
  const unit = options.unit ?? "sq. units";
  const area = width * height;
  return `${area} ${unit}`;
}
84
Q

When using a try/catch block, how should we type the error passed to the catch block?

A

We should catch the exception using an unknown type. We need to do this because technically in JavaScript you can throw any type and it is a type safe alternative to any. Within the catch block we must then use type guards (instanceof works well here) to narrow the error’s type and then handle the error appropriately. If we cannot narrow the error’s type, rethrow the error.

85
Q

<K extends keyof T>
The above code can be read as…

A

K extends keyof T means that the type of K (K being a generic type variable) must be a subset of the keys of T.

85
Q

What is the syntax for Promise types in TypeScript?

A

When you are defining a promise type in TypeScript you use Promise and then provide the type that the promise resolves to.

Some examples of how to properly define promise types:

Promise<string>
Promise<number
Promise<T>

86
Q

function someFunc<T extends { age: number }>
The above code is an example of defining a generic constraint and can be read as…

A

T is a subset of { age: number }

87
Q

What is Pick?

A

Pick<T, K extends keyof T> is a utility type in TypeScript that allows us to create a new type from an existing type by specifying specific properties of T that we want our new type to be composed of. If you specify a property that is not in T there will be a type error.

88
Q

What is Omit?

A

Omit<T, K extends keyof any> is a utility type in TypeScript that allows us to create a new type from an existing type by specifying the specific properties from T that we do not want included in the new type. If you specify a property that is not in T no type error will be given.

89
Q

What is ReturnType<T>?

A

ReturnType is a TypeScript utility type that extracts the return type of a function (type).

90
Q

What is the TypeScript operator typeof?

A

The TypeScript typeof operator returns the complete type of the given value that is inferred by the TypeScript compiler

91
Q

What is Parameters<T>?

A

Parameters<T> is a TypeScript utility type that returns a tuple of the parameter types of a function.

92
Q

Given the following code, what will the type of SumParameters be equivalent to?

function sum(prefix: string, ...numbers: number[]): string { const total = numbers.reduce((total, n) => total + n, 0); return ${prefix}${total}; }

type SumParameters = Parameters<typeof sum>;

A

Parameters<typeof sum> evaluates to a tuple type that is equivalent to [string, ...number[]].

93
Q

What is Partial<T>?

A

Partial<T> is a TypeScript utility type that creates a new type based on an existing type, where all of the type’s properties are optional.