The Basics Flashcards

1
Q

Declare a let called gen for a generic type called GenericType that takes 2 Specific types: SpecificType1 and SpecificType2

A
let gen : GenericType<SpecificType1, SpecificType2, ...>;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Create a let called coordinates and assign it to an array of coordinate using this type:

type Coordinate = [number, number];
A
let coordinates: Array<Coordinate>;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Will this yield an error:

type Coordinate = [number, number];

let coordinates: Array<Coordinate>;

coordinates = [
  [30, 100, 0],
  [100, 50],
];
A

Yes, because each coordinate can only have 2 dimensions.

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

Create a let called result that is a generic promise to return something of type Response.

If you don’t know the Type Response see:
https://developer.mozilla.org/en-US/docs/Web/API/Response

A
let result: Promise<Response>;

This is useful when fetching information from api like so:

let promisedResponse: Promise<Response> = fetch("https://myapi.dev/api/");
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How can we use the result of this to output if the response was OK?

const promisedResponse: Promise<Response> = fetch("https://swapi.dev/api/");
A
promisedResponse.then((res) => console.log(res.ok));
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How can we narrow the type of the record keys so that only ‘rodj’ or ‘janes’ are accepted?

type Result = {
  firstName: string;
  surname: string;
  score: number;
};
type ResultRecord = Record<string, Result>;

const records: ResultRecord = {
  rodj: {
    firstName: "Rod",
    surname: "James",
    score: 70,
  },
  janes: {
    firstName: "Jane",
    surname: "Smith",
    score: 95,
  }
};

A

By changing the ResultRecord type definition from:

type ResultRecord = Record<string, Result>;

to:

type ResultRecord = Record<"rodj"|"janes", Result>;

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

Make this function generic:

function firstOrNull(array: string[]): string | null {
  return array.length === 0 ? null : array[0];
}
A
function firstOrNull<T>(array: T[]): T | null {
  
  return array.length === 0 ? null : array[0];
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Declare an array and bind it to a variable called myArray for the class Product without using:

 new Array aka Array<Product>:
class Product {
    name: string;
    desc: string;
    meta: string
}
A
let myArray : Product[];

Note: if you use const you have to initialize the array like so:

const myArray: Product[] = [];
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Can interfaces be generic and accept multiples types ?

A

Yes. A common use if for forms.

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

Create a typed const contactForm using these 2 interfaces and assign a first value of “bob” and “bob@someemail.com” to contactForm:

interface Form<T> {
  values: T;
}

interface Contact {
  name: string;
  email: string;
}
A
const contactForm: Form<Contact> = {
    values: {
        name: "Bob",
        email: "bob@someemail.com"
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Explain this interface and what the K in keyof T is…

interface Form<T> {
  values: T;
  errors: {
    [K in keyof T]?: string;
  };
}
A
  1. The type is in curly brackets, so we are constructing an object type.
  2. [K in keyof T] will put all the keys in the type T into a string literal union. This will be “name” | “email” for contactForm.
  3. [K in keyof T] is the property name of the object being constructed (T).
  4. The ? after the property name means the properties are optional.
  5. The type for the properties is string.

So given a T that would be an interface:

interface Contact {
  name: string;
  email: string;
}

The type for the errors is:

 {name?: string; email?: string}.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Is it possible to pass types into a type alias ?

A

Yes. Using this syntax:

type TypeName<T1, T2, ...> = {
 ...
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Implement a generic Form type with 2 properties:
values for our generic T
and an
optional errors for each key of T

A
type Form<T> = {
  values: T;
  errors: { [K in keyof T]?: string };
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Can we declare generic classes ?

A

Yes

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

What is the syntax to create a generic class using T1,T2,T3..

A

class ClassName<T1, T2, …> {

}

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

Create a generic class called List that will take a single generic type T and keep the items in a private array of T called items.

A
class List<T> {
  private items: T[] = [];
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Add a add method on this class to add an item of type T.

This new add method needs to push a provided item of type T in private Items.

class List<T> {
  private items: T[] = [];
}
A
class List<T> {
  private items: T[] = [];

 add(item: T){
    this.items.push(item);
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Can generic parameter have a default value?

A

Yes

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

How do we specify a default on a generic type T ? Provide an example where the type is called TypeName the generic type if T and the default type of T is DefaultType.

A
type TypeName<T= DefaultType> ={
  ...
}
20
Q

Will this raise any error?

interface Component<T1 = string, T2 = any> {
  name: T1;
  props: T2;
  log: () => void;
}

const button: Component = {
  name: "Button",
  props: {
    text: "Save",
  },
  log: () => console.log("Save button"),
};

console.log(button.props.text);
console.log(button.props.text2);
A

No. Because absolutely no type checking is done on T2 since it’s any.

Note: When a generic parameter default is used, the type might be wider than necessary.

21
Q

Will this yield an error:

function firstOrNull<T>(array: T[]): T | null {
  return array.length === 0 ? null : array[0];
}

const first = firstOrNull([1, 2, 3]);
console.log(first);
A

No. Even if we didn’t supply the generic parameter to the function. Generic parameters aren’t required on functions. In this case, the parameter has been inferred to be number.

22
Q

Supply a default type of string for T in this function:

function firstOrNull<T>(array: T[]): T | null {
  return array.length === 0 ? null : array[0];
}
A
function firstOrNull<T = string>(array: T[]): T | null {
  ...
}
23
Q

Given this code:

function firstOrNull<T = string>(array: T[]): T | null {
  return array.length === 0 ? null : array[0];
}

const first = firstOrNull([1, 2, 3]);
console.log(first);

What will be the type of first?

A

first has been inferred to be number. The default generic parameter type was overridden by the type inference of the function parameters.

24
Q

Is it possible to require generic parameters to have a particular structure?

A

Yes

25
Q

How do we put a constraint of ConstrainingType on a generic parameter T?

A

<T extends ContrainingType>

26
Q

Will this raise an error? If so why?

interface Logable {
  log: () => void;
}

function logItems<T>(items: T[]): void {
  items.forEach(item => item.log());
}
A

Yes. TypeScript doesn’t know that the array items contain a log method, so, it raises an error.

27
Q

This function will raise an error since Typescript doesn’t know that the item implement .log(). Fix this by adding a parameter constraints on the generic type.

interface Logable {
  log: () => void;
}

function logItems<T>(items: T[]): void {
  items.forEach(item => item.log());
}
A
interface Logable {
  log: () => void;
}

function logItems<T extends Logable>(items: T[]): void {
  items.forEach(item => item.log());
}
28
Q

Can a generic parameter constraint be dependent on another generic parameter?

A

Yes

29
Q

This raise an error. Why?

interface Form<T> {
  values: T;
}
function getFieldValue<T>(form: Form<T>, fieldName: string) {
  return form.values[fieldName];
}
A

TypeScript doesn’t know what the structure of value is, so, it raises an error.

30
Q

This raise an error:

interface Form<T> {
  values: T;
}
function getFieldValue<T>(form: Form<T>, fieldName: string) {
  return form.values[fieldName];
}

Fix it using parameter constraint.

A
interface Form<T> {
  values: T;
}
function getFieldValue<T, K extends keyof T>(form: Form<T>, fieldName: K) {
  return form.values[fieldName];
}

Note: The TypeScript keyof keyword queries the keys of the type referenced after it.

31
Q

What is the rest element?

A

A rest element type is a type for a collection of tuple elements.

32
Q

Is it possible to use generic rest elements?

A

Yes. For example:
type NameAndThings<T extends unknown[]> = [string, ...T];

33
Q

Add labels to make the structure of the tuple a little more readable. Add a label name and things to this code:

type NameAndThings<T extends unknown[]> = [string, ...T];
A
type NameAndThings<T extends unknown[]> = [name: string, ...things: T];
34
Q

Using this type:
type NameAndThings<T extends unknown[]> = [name: string, ...things: T];
Declare a let variable named scores to hold the following numeric scores for bob: 4,5 and pass in bob’s name.

A
let scores: NameAndThings<number[]>;
scores = ["Bob", 4, 9, 3];
35
Q

Using this function declare a variable to hold grades scores for Bill using our NameAndThings type. The tuple should contain a string-based name in the first element and grades in subsequent elements. The grades can only be ‘A’, ‘B’, or ‘C’.

type NameAndThings<T extends unknown[]> = [name:string, ...things:T];
A
type NameAndThings<T extends unknown[]> = [name:string, ...things:T];

type Grade = "a"|"b"|"c";

let billGrades : NameAndThings<Grade[]>;
  billGrades = ["bill","a","b","c"]

///or 

let billGrades: NameAndThings<("A" | "B" | "C")[]>;
36
Q

Will this raise an error:

function logThings<T extends unknown[]>(name: string, ...things: T) {
  console.log(things);
}

logThings("Bob", 4, 9, 3);
A

No. TypeScript cleverly infers the generic parameter type from the parameter values.

37
Q

Will this raise an error:

function logThings<T extends unknown[]>(name: string, ...things: T) {
  console.log(things);
}

logThings("Bob", 4, "9", 3);
A

No, TypeScript infers the generic parameter type to be [number, string, number].

38
Q

Will this raise an error:

function logThings<T extends unknown[]>(name: string, ...things: T) {
  console.log(things);
}

logThings<number[]>("Bob", 4, "9", 3);
A

Yes, because ‘9’ is not a number type.

39
Q

Can function parameter be thought of as a tuple?

A

Yes. Typing function parameters as a tuple allow strongly-typed functions to be created that have varying parameters.

40
Q

What will be the type of scores in:

function merge(names: string[], scores: number[]) {
  return [...names, ...scores];
}

let scores = merge(["Bill", "Jane"], [8, 9]);
A

(string | number)[]

41
Q

What are Names and Scores in this function:

function merge<Names extends string[], Scores extends number[]>(
  names: Names,
  scores: Scores
) {
  return [...names, ...scores];
}
A

Generic parameter types

42
Q

What is the type of scores here:

function merge<Names extends string[], Scores extends number[]>(
  names: Names,
  scores: Scores
) {
  return [...names, ...scores];
}

let scores = merge(["Bill", "Jane"], [8, 9]);
A

(string | number)[]

43
Q

What is the type of scores here:

function merge<Names extends string[], Scores extends number[]>(
  names: [...Names],
  scores: [...Scores]
) {
  return [...names, ...scores];
}

let scores = merge(["Bill", "Jane"], [8, 9]);
A

(‘Bill’ | ‘Jane’ | 8 | 9)[]

44
Q

We are using the spread operator here to specify the return type. What will be the type of scores:

function merge<Names extends string[], Scores extends number[]>(
  names: [...Names],
  scores: [...Scores]
): [...Names, ...Scores] {
  return [...names, ...scores];
}

let scores = merge(["Bill", "Jane"], [8, 9]);
A

[‘Bill’, ‘Jane’, 8, 9]

45
Q

We have a function below which outputs the name property of an object to the console. How can we use generics to make this more strongly-typed?

function logName(object: any) {
  console.log("My name is " + object.name);
}
A

function logName<T extends {name: string}>(object: T) {
console.log(“My name is “ + object.name);
}

46
Q

What is the syntax to add T1, T2 to a type of TypeName?

A
type TypeName<T1, T2, ...> = {
 ...
}