StartsWith
Challenge
Implement StartsWith<T, U>
which takes two exact string types and returns
whether T
starts with U
. For example:
type a = StartsWith<"abc", "ac">; // expected to be false
type b = StartsWith<"abc", "ab">; // expected to be true
type c = StartsWith<"abc", "abcd">; // expected to be false
Solution
Knowing about template literal types in TypeScript, the solution becomes really
obvious. Let’s start with an initial type that holds any
type:
type StartsWith<T, U> = any;
We need to check if the input type parameter T
starts with a string literal
from U
. I’ll do it simpler and just check if the T
is U
by using
conditional types:
type StartsWith<T, U> = T extends `${U}` ? never : never;
If the input type parameter T
is the same as in type parameter U
, we will go
into the true branch of the conditional type. But, we don’t need them to be
equal. We need to check if it starts with U
. In other words; we don’t care if
there will be something after the U
in our literal type. So that, use any
type there:
type StartsWith<T, U> = T extends `${U}${any}` ? never : never;
If type T
matches the pattern of a string that starts with U
, we return the
true
literal type. Otherwise, return false
:
type StartsWith<T, U> = T extends `${U}${any}` ? true : false;
We got all the test cases passed, but we still got a compilation error saying
“Type ‘U’ is not assignable to type ‘string | number | bigint | boolean | null |
undefined’.“. That’s because we didn’t add a constraint over generic to show
that U
is a string. Let’s add it:
type StartsWith<T, U extends string> = T extends `${U}${any}` ? true : false;
Comments