I'm pretty new to typescript, this was probably answered before, but I can't find the answer anywhere, so here is the problem I'm trying to solve.
I have an enum
enum TableNames = {
example: 'example'
example2: 'example2',
}
and I have these types for my models
type TableName = keyof typeof TableNames
type TableState<L =any> = {
list: Array<L>
}
type ExampleDataType = {
id: string
...
}
type ExampleData2Type = {
id: number
...
}
type TableStateType = {
example: TableState<ExampleDataType>
example2: TableState<ExampleData2Type>
}
type InterListType<TName extends TableName> = TableStateType[TName]['list'][number]
and I have this special function
const createPath = <TName extends TableNames, T = InferListType<TName>>(
tableName: TName,
record: T
) => {
if (tableName === TableNames.example) {
console.log(record) // how to get this to infer to "ExampleDataType"
}
if (tableName === TableNames.example2) {
console.log(record) // how to get this to infer to "ExampleData2Type"
}
}
The question is the comment above, right now I'm getting this
if (tableName === TableNames.example) {
console.log(record) // T = InferListType<TName>
}
NOTE: typescript version is 3.7.4
CodePudding user response:
You are running into this issue: Typescript - How do I narrow type possibilities of a generic type in a switch statement?.
Here's why [it] won't work: Typescript has control-flow type narrowing for variables like
tableName
, but not for type parameters likeT
.
JCalz mentions a workaround in the comments that might help. Looks something like this:
type ExampleDataType = {
id: string
data1: string
}
type ExampleDataType2 = {
id: string
data2: string
}
type TableToRecordMap = {
example: ExampleDataType
example2: ExampleDataType2
}
type TableName = keyof TableToRecordMap
type TableState<L =any> = {
list: Array<L>
}
type TableStateType = {
[Table in TableName]: TableState<TableToRecordMap[Table]>
}
const createPath = <TName extends TableName>(
tableName: TName,
record: TableToRecordMap[TName]
) => {
const partialTable: Partial<TableToRecordMap> = { [tableName]: record };
if (partialTable.example) {
console.log(partialTable.example)
} else if (partialTable.example2) {
console.log(partialTable.example2)
}
};