0

I am looking for a way to correctly express my data model with tyepscript definitions. So far I have the following:

type Data = Record<string, string>;

interface DataContainer<D extends Data> { 
    id: string;    
    data: D;
}

interface Context {
    dataContainers: DataContainer<any>[];
}

Typescript Playground

A Context stores a set of DataContainers, where each DataContainer is generic over a specific data structure D. Now what I want to express is that each of those data structures D should follow a universal type Data. I.e. consisting of arbitrary but fixed <string, string> pairs.

I really could not find a proper solution for that, the best thing I found was DataContainer<D extends Data>. Do you think that's a good approach?

At least the following gives my a linting error as desired:

interface MyData extends Data {
    x: "1",
    y: 2, // Lint error, because not string. (As I want it)
}

So I conclude that when writing <D extends Data> it would also not be allowed for D to have an entry like y: 2, correct?

Now a real problem for me is that the following does not give me a linting error:

const myContext: Context = {
    dataContainers: [
        {
            id: "123",
            data: {
                x: 1, // This should be marked by the linter
                y: "2", 
                z: {a: 1}, // This also
            }
        }
    ]
}

I am looking for a way to model my definitions such that a linter would mark this as invalid, because there exists no D such that the above would be a valid Context. Is that possible? Thanks for your help!

1
  • Notpick: TS is a language not a linter :P Commented Mar 18, 2020 at 16:16

1 Answer 1

1

You are close. The issue is with DataContainer<any>. Any effectively turns off type checking where it is used. This means that since data in DataContainer<any> will be of type any, no checks will be done for the property. This is regardless of the constraint you put on D

The simple solution is to not use any, use the constraint as the type argument to DataContainer:


interface Context {
    dataContainers: DataContainer<Data>[];
}

Playground Link

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

1 Comment

Thank you! That did it for me!

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.