Witee
Witee

Reputation: 21

How to constraintvalues in typescript?

tsc version: 3.9.6

I want to constrain the value of getColDict().

In my interface ColDict<T>, key is any string, value must be T, in my case T is type Column.

My code is here:

interface ColDict<T> {
  [i: string]: T;
}

function getColDict<T>(): ColDict<T> {
  return {
    id: { title: 'ID', dataIndex: 'id' },  // **constraint here**
    name: { title: 'NAME', dataIndex: 'name' },  // **constraint here**
    xxx: { title: 'YYY', dataIndex: 'zzz' },  // **constraint here**
  };
}

// =====================================

export type Column = {
  title: string;
  dataIndex: string;
  width: number;
};

const colDict = getColDict<Column>();

const columns: Column[] = [
  { ...colDict.id, width: 80 },
  { ...colDict.name, width: 80 },
  { ...colDict.xxx, width: 80 },
];

console.log('columns: ', columns);

I get the error:

id: { title: 'ID', dataIndex: 'id' },
~~

Type '{ title: string; dataIndex: string; }' is not assignable to type 'T'.
  'T' could be instantiated with an arbitrary type which could be unrelated to '{ title: string; dataIndex: string; }'.ts(2322)

How can I do this?

Upvotes: 2

Views: 227

Answers (1)

ccarton
ccarton

Reputation: 3666

I can see what you are trying to do. There are a few issues. Firstly, getColDict() shouldn't be generic because nothing in the implementation depends on the generic parameter. You don't enforce constraints that way. Instead you should explicitly define the column interface that getColDict() generates and then TS will give you an error if you try to assign the return value to an object of a different type. It would look like this:

interface ColDict<T> {
  [i: string]: T;
}

interface ColumnType {
  title: string
  dataIndex: string
}

function getColDict(): ColDict<ColumnType> {
  return {
    id: { title: 'ID', dataIndex: 'id' },  // **constraint here**
    name: { title: 'NAME', dataIndex: 'name' },  // **constraint here**
    xxx: { title: 'YYY', dataIndex: 'zzz' },  // **constraint here**
  };
}

// =====================================

export type Column = {
  title: string;
  dataIndex: string;
  width: number;
};

const colDict: ColDict<Column> = getColDict(); // Error, Property 'width' is missing in type 'ColumnType' but required in type 'Column'.

Upvotes: 1

Related Questions