1

I have a string that I want to split and the result of the split string will be very specific, which I want to type:

const [validator, argument]: [keyof typeof validators, string] = validation.split(':');

I know that the validator will be keyof typeof validators but I am getting an error in TS:

TS2739: Type 'string[]' is missing the following properties from type '[string | number, string]': 0, 1

What is it about this that TypeScript does not like? I have searched around and cannot find an answer to this problem.

2 Answers 2

4

.split returns an Array<string>, not a tuple. You will have to use as any and explicitly cast if you are really sure of what you are doing or write a function that checks the output for you.

With any:

const [validator, argument]: [keyof typeof validators, string] = validation.split(':') as any;

Safer, but you will have to deal with the error return possiblity:

const isKeyOf = <T extends object>(k: string | keyof T, obj: T): k is (keyof T) => obj.hasOwnProperty(k)

const safer = (from: string): [keyof typeof validators, string] => {
  const [first, second] = string.split(":)

  if (first && second && isKeyOf(first, validators)) {
    return [first, second]
  }

  return Error("Not a valid input.")
}
Sign up to request clarification or add additional context in comments.

3 Comments

I'd recommend staying away fromany unless you can't proceed without it. In this case, you can use the type assertion const [validator, argument] = validation.split(":") as [keyof typeof validators, string]; instead of as any; it still works and is somewhat safer.
@jcalz This is what I was looking to do. I am already checking to make the key is in the object, so all I needed to do is to cast it. If you want to make this an answer, I will mark it correct.
I've undeleted my answer but I think this answer is essentially correct with the possible exception of using any instead of the stricter type.
3

Please note that @chautelly's answer is correct, with the only possible issue being that the assertion to any is much looser than is needed to get this working, and I'd suggest asserting to the tuple directly. If that answer gets updated to take this into account, I'd be happy to remove this.


TypeScript doesn't know that split() will return a pair (a two-tuple). It only knows that it will return a string[]. So the error is saying that string[] (what split() returns) might not have properties at the 0 and 1 keys that a pair does, and thus it isn't safe to assign it to your pair type.

In the case where you know that what you are doing is safe (meaning you've somehow already constrained validation to be a string with exactly one colon in it where the prefix is one of the keys of validation), you can use a type assertion:

const [validator, argument] = validation.split(":") as [
  keyof typeof validators,
  string
]; // okay now

Type assertions will let you unsafely narrow the type of an expression, meaning you can tell the compiler that an expression is of a more specific type than it can verify. The compiler knows that validation.split() returns a string[], and you are asserting that it is specifically a [keyof typeof validators, string], a subtype of string[].

Do note that type assertions allow you to lie to the compiler, and therefore the responsibility is on you not to do this. If, at runtime, it turns out that validation has a different value from what you're expecting, then weird things will happen and the compiler cannot possibly help you avoid those. If you want help avoiding those, then you will probably need to use type guards of some sort to actually verify that a string[] is of the pair type you expect. If you are already doing this test somewhere, it might be worthwhile to rewrite this test in a form that the compiler perceives as a type guard.

Okay, hope that helps; good luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.