2

I have an interface like this. And I am wondering what is the best case to handle this case:

interface Ia {
  a: string
}
let a: Ia | Ia[]
console.log(a[0].a)

TS throws me an error:

Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'Ia'.
  Property '0' does not exist on type 'Ia'.

I know I could use console.log((a as Ia[])[0].a) but it is not readable at all. Does anyone have better suggestions?

Also, the real use case type has many properties inside not the single one a: sting as in the example.

2
  • 1
    If you know that a is an array, why then you say it is Ia | Ia[] ? Commented Feb 7, 2020 at 11:50
  • @MaciejSikora I am getting the data structure and it might be a list or a single value. I will have a check for that, but my question is about options to handle the actual type assignation and to check if there are any alternatives to as Commented Feb 7, 2020 at 11:55

3 Answers 3

3

If a is not an array, then a[0] does not make sense. You need to test whether it is an array, and treat it differently depending on the result of that test.

interface Ia {
  a: string
}

let obj: Ia | Ia[] = { a: 'foo' };

function test(obj: Ia | Ia[]): void {
  console.log(Array.isArray(obj) ? obj[0].a : obj.a);
}

Or you can use this pattern, which takes advantage of control-flow type narrowing:

function test2(obj: Ia | Ia[]): void {
  if (Array.isArray(obj)) { obj = obj[0]; }
  // now obj: Ia is known not to be an array
  console.log(obj.a);
}

Playground Link

Sign up to request clarification or add additional context in comments.

Comments

1

I have settled with:

interface Ia {
  a: string
}
let a: Ia | Ia[]
if (Array.isArray(a)){
  a = [a]
}
console.log(a[0].a)

Thank you @kaya3 and @maciej-sikora for suggestions

Comments

0

I propose create a getter for that, consider:

const getA = (x: Ia | Ia[]) => "a" in x ? x.a : x[0]?.a;

const a = getA({ a: 'I am a' });
const a2 = getA([{ a: 'I am also a ' }]);

Or uniform the type and use it always in the same way:

const uniform = (x: Ia | Ia[]): Ia => Array.isArray(a) ? a[0] : a;

Such function unify our type from the union to one member.

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.