Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare group of strings as a type?

Tags:

typescript

I would like to enforce a group of strings as a strict type. Users should be only be able to pass in anything that matches a string in the group. How would I go about implementing this?

This is what I have so far:

const types: Array<string> = [ 'text', 'password' ];

interface IAbstractFormElement {

  value: string;
  type: Array<types>;
  required?: boolean;
  disabled?: boolean;

}

Current error: Cannot find name 'types' which almost seems like a scope issue to me.

like image 871
Christopher Marshall Avatar asked Sep 11 '25 19:09

Christopher Marshall


2 Answers

If you know in advance what are the possible values are for the type property then you can use string literals:

type types = "text" | "password";

const types: types[] = ["text", "password"];

interface IAbstractFormElement {
    value: string;
    type: types;
    required?: boolean;
    disabled?: boolean;
}

(code in playground)

like image 86
Nitzan Tomer Avatar answered Sep 14 '25 10:09

Nitzan Tomer


In your code, types isn't a type, it's a const value. You will have to take a different approach.


One approach is to use an enumeration:
enum InputType {
    Text = 1,
    Password  = 2
}

let t: InputType = InputType.Text;

But enumerations are really just a named number. There isn't any safety enforced by the compiler.

For example, the typescript compiler would compile, without error, nonsense like this:

let t:InputType = InputType.Text;
t = InputType.Password;
t = 72;
t = Math.PI; 


To strictly enforce a limited number of values, you can create a dedicated class:
class InputType {
    private static Instances = {
        Text: new InputType("text"),
        Password: new InputType("password")
    };

    private constructor(private _name:string) {
    }

    get Name() : string {
        return this._name;
    }

    static get Password() : InputType{
        return InputType.Instances.Password;
    }

    static get Text(): InputType{
        return InputType.Instances.Text;
    }
}

Because the constructor is private, the rest of your code cannot create one of these. It will have to access a predefined value via a static getter method.

Using this in the interface you defined:

interface IAbstractFormElement {
  value: string;
  type: InputType;
  required?: boolean;
  disabled?: boolean;
}

var nameControl = <IAbstractFormElement>{
     value: 'Harold',
     type: InputType.Text
};
var passwordControl = <IAbstractFormElement>{
     value: 'P@ssw0rd',
     type: InputType.Password
}
like image 34
Andrew Shepherd Avatar answered Sep 14 '25 11:09

Andrew Shepherd