3

I want to check if a string has a prefix that matches a union type, eg:

type Prefix = "ABC" | "DEF" | "GHI" ...;
const hasPrefix = (str: string): boolean => {
   // I want to check the first 3 characters of the string
   // And see if it matches any of the Prefix
   // Something like
   //  if (str.substr(0, 3) === Prefix)
}
Kousha
  • 32,871
  • 51
  • 172
  • 296
  • 1
    I guess the problem is how to use `Prefix` type with built-in methods, right? It seems like only custom logic, like in your comment, applies (type string, then a check). – Georgy Jun 24 '19 at 01:17
  • 1
    Why would you want to check against a type instead of just an array of prefix strings? What's your use case? – Mu-Tsun Tsai Jun 24 '19 at 07:57

2 Answers2

2

I think it is not possible at the moment just with built-in Typescript types. https://github.com/Microsoft/TypeScript/issues/6579 and for reference to proposals: How to define a regex-matched string type in Typescript?

Georgy
  • 2,410
  • 3
  • 21
  • 35
2

In the current version of TypeScript you can't dissect a union type. For your problem I would recommend an approach using enums like so:

enum Prefixes {
    "ABC",
    "DEF",
    "GHI"
}

const hasPrefix = (str: string): boolean => Prefixes[str.substr(0, 3) as any] !== "undefined";

console.log(hasPrefix("123")); // false
console.log(hasPrefix("ABC")); // true
console.log(hasPrefix("DEF")); // true
console.log(hasPrefix("GHI")); // true
console.log(hasPrefix("GHII"));// true

const data = "ABC123";         // ABC123

console.log(hasPrefix(data));  // true
console.log(data);             // still ABC123

Here's a TypeScript playground of the above code.


Judging by your question you seem to be interested in a dynamic way to check for prefixes (the ... characters imply this (?)). This got me thinking and came up with a solution using a Set data type. Consider this example:

// Set data type ensures only uniques
type Prefix = string;
const prefixes: Set<Prefix> = new Set();

prefixes.add("ABC");
prefixes.add("ABC");
prefixes.add("DEF");
prefixes.add("GHI");

// No doubles here so we're good (note the double added ABC string)
console.log(prefixes);

// the typeguard
const hasPrefix = (str: any): str is Prefix => typeof str === "string" ? prefixes.has(str.substr(0, 3)): false;

console.log(hasPrefix(100));   // false
console.log(hasPrefix(0));     // false
console.log(hasPrefix(false)); // false
console.log(hasPrefix(true));  // false
console.log(hasPrefix(""));    // false
console.log(hasPrefix("123")); // false
console.log(hasPrefix("ABC")); // true
console.log(hasPrefix("DEF")); // true
console.log(hasPrefix("GHI")); // true
console.log(hasPrefix("GHII"));// true

const data = "ABC123";         // ABC123

if (hasPrefix(data)) {
    console.log(hasPrefix(data));  // true
    console.log(data);             // still ABC123
}

Here's the playground for that code.

Alex
  • 838
  • 1
  • 14
  • 16
  • 1
    In your first code snippet, using `typeof Prefixes[str.substr(0, 3)] !== "undefined"` [would be more appropriate](https://stackoverflow.com/a/4725697/5784924) – Nicolas Feb 03 '20 at 20:17
  • 1
    @Nicolas thank you for your feedback, I updated the first example. – Alex Feb 03 '20 at 21:38