3

Assume I have the following:

export const ContentType = {
    Json: "application/json",
    Urlencoded: "application/x-www-form-urlencoded",
    Multipart: "multipart/form-data",
};

export interface RequestOptions {
    contentType: string,
}

const defaultOptions: Partial<RequestOptions> = {
    contentType: ContentType.Json,
};

How would I go about restricting contentType so that only keys declared in ContentType are used?

Alexander Trauzzi
  • 7,277
  • 13
  • 68
  • 112

2 Answers2

11

This is my preferred way as of TypeScript 2.1:

export const contentTypes = {
    "application/json": true,
    "application/x-www-form-urlencoded": true,
    "multipart/form-data": true
};

type ContentType = keyof typeof contentTypes;

export interface RequestOptions {
    contentType: ContentType;
}

const defaultOptions: Partial<RequestOptions> = {
    contentType: "application/json",
};

Try it in TypeScript Playground

  • Define a set of valid strings in an object literal.
  • Create a type that contains the keys of that object, using keyof. It's a string union type.
  • Type your string property to that union type, and the compiler will only allow those strings.
Robert Penner
  • 6,148
  • 1
  • 17
  • 18
  • Can't believe I stumbled upon the famous Robert Penner in the wild! Just wanted to say I'm a huge fan. – M - Aug 11 '17 at 21:39
1

You can use string literal types. Instead of typing contentType as string, type it as a literal type of possible values.

export interface RequestOptions {
    contentType: "application/json" | "multipart/form-data" | "multipart/form-data:"
}

To avoid repeating your constants you can declare them separately and type contentType as typeof ConstantString:

export const ContentTypeJson = "application/json";
export const ContentTypeUrlencoded = "application/x-www-form-urlencoded";
export const ContentTypeMultipart = "multipart/form-data";


export interface RequestOptions {
    contentType: typeof ContentTypeJson| typeof ContentTypeUrlencoded | typeof ContentTypeMultipart,
}

const defaultOptions: Partial<RequestOptions> = {
    contentType: ContentTypeJson,
};
Saravana
  • 37,852
  • 18
  • 100
  • 108
  • Issue I have with this is that I'm just repeating the value everywhere. While I get enforcement that only valid values are used, I'm still repeating them. – Alexander Trauzzi Apr 15 '17 at 20:23
  • @Omega I have updated the answer with another approach where you don't have to repeat constants. – Saravana Apr 16 '17 at 00:49