5

I'm having a lot of trouble understanding the intersection types. Here it is what I'm referring to:

type FooList = Foo[] & {
    bar: string
};

interface Foo {
    baz: string;
}

After a lot of fiddling I'm unable to create a typed array of FooList.

These typings are not mine, they are from this library.

Does these types mean FooList must be an array of Foos and also have an object bar? Does each Foo object has to contain a property bar?

Here is the link to the playground

3 Answers 3

4

A FooList is both an array of Foo objects, as well as an object that contains a string-valued bar property.

If you're willing to use type assertions, it's easy enough to create one since you can just tell the compiler you know what you're doing:

var foos: any; // turn off type checking
foos = [{ baz: 'baz1' }, { baz: 'baz2' }];
foos.bar = 'bar';
var fooList: FooList = foos as FooList; // assert type of fooList

Creating one of these things safely, where the compiler guarantees that you've made something of the right type is a little tricky, but you can do it with Object.assign(), which returns an intersection of its parameter types:

const fooList: FooList = Object.assign([{ baz: 'baz' }, { baz: 'baz' }], { bar: 'bar' });

Hope that helps. Good luck!


Please ignore the stuff below; I'm not sure what came over me, but spreading an array into an object is unlikely to work the way anyone wants, since Array prototype methods will not be copied. Just use the above Object.assign() solution.

Update 1

@CésarAlberca said:

Thanks! Yours was my preferred solution. What is the equivalent of object assign using the spread operator?

Oh, sure, you could do that:

const fooList2: FooList = { ...[{ baz: 'baz' }, { baz: 'baz' }], ...{ bar: 'bar' } };

or

const fooList3: FooList = { ...[{ baz: 'baz' }, { baz: 'baz' }], bar: 'bar' };

Cheers.

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

3 Comments

I am not sure how this works, but apparently I am getting TS lint warnings as below: TS2201: The types returned by 'sort(...)' are incompatible between these types.   Type '{ baz: string; }[]' is not assignable to type 'FooList'.     Property 'bar' is missing in type '{ baz: string; }[]' but required in type '{ bar: string; }'.
Hmm, even without the warnings, spreading an array into an object is a bad idea (since the resulting object will not have any of the expected Array prototype methods). I'm not sure why I suggested that above. Shame on you, jcalz-from-almost-three-years-ago! The Object.assign() solution is better and should work.
Cool, thanks for the quick reply. In my case I just provided one more key for the array and made it into a project object inherently, which is also a lot more readable.
1

FooList is an array with items of type Foo which also has a string property named bar.

Here's how you'd create it:

function createFooList(bar: string, ...items: Foo[]): FooList {
    const arr = [] as FooList;
    arr.bar = bar;
    arr.push(...items);
    return arr;
}

Or:

function createFooList(bar: string, ...items: Foo[]): FooList {
    (items as FooList).bar = bar;
    return items as FooList;
}

Comments

0

Look at my demo of usage.

type LinkedList<T> = T & { next: LinkedList<T> };

interface Person {
    name: string;
}

var people: LinkedList<Person>;
var person: Person = { name: "Joey" };
var childPerson: Person = { name: "James" };
var grandChildPerson: Person = { name: "John" };

people = person;
people.next = childPerson;
people.next.next = grandChildPerson;

alert(JSON.stringify(people));

See typescript documentation of type aliases and intersection types

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.