5

Give then following:

interface Datum {
    [k: string]: any
}

type Data = Datum[]

const inner = (data: Data) => {
    console.log(data)
};


const outer = (data: Data | Data[]) => {
    inner(data) // expect type error?
};

I dont understand how I dont get a type error on the inner function call. I guess it has something to do with the generic. Cant figure out a way of rewriting.

3
  • I think it's because you defined an array here type Data = Datum[] Commented Mar 14, 2019 at 21:59
  • @JohnMontgomery: I think the OP expects to get an error but isn't. Commented Mar 14, 2019 at 22:00
  • @FelixKling Ah, I misread the question. Commented Mar 14, 2019 at 22:01

2 Answers 2

5

The Datum interface is just too broad. It will represent basically any object (ie indexable by a string and the result of the indexing operation is any).

Given the object type is soo wide, both Datum and Datum[] and Datum[][] are assignable to an array type, and thus you don't get any error. Make the interface a bit more specific and you get an error. Ex:

interface Datum {

    [k: string]: boolean | number | string;
}

type Data = Datum[]

const inner = (data: Data) => {
    console.log(data)
};


const outer = (data: Data | Data[]) => {
    inner(data) // error now
};

Or as @PatrickRoberts mentions in comments you can add a number index to the interface to make it explicitly incompatible with an array:

interface Datum {
    [i: number]: never
    [k: string]: any;
}

type Data = Datum[]

const inner = (data: Data) => {
    console.log(data)
};


const outer = (data: Data | Data[]) => {
    inner(data) // error
};
Sign up to request clarification or add additional context in comments.

4 Comments

Could also add [i: number]: never to Datum instead of modifying the string keyed signature.
@PatrickRoberts good solution, mind if I add it to the answer ?
Not at all, that's why I suggested it since you already had the same explanation as I would have given :)
Thanks - really appreciate that. New it was something to do with that.
2

The best option would probably be using directly the object interface instead of Datum:

interface Datum {
    [k: string]: any
};
// This is an object interface.

type Data = object[]; // instead of Datum[]


const inner = (data: object[]) => {
    console.log(data)
};

Pd: I was looking for a solution for this same issue, used the solution from @titian-cernicova-dragomir which worked nicely. I ended up finding the object interface being used in the react-csv library.

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.