TypeScript 2.8 条件类型问题
TypeScript 2.8 Conditional Type Issue
在遇到 TS 2.6 中的问题后,我一直在试验 TypeScript 2.8 的条件类型,但我 运行 遇到了一个我不理解的错误,需要一些帮助:
这个例子涉及到这个问题。
export class Column<T> {
readonly base: T
constructor(base: T) {
this.base = base
}
}
export class ColumnExpression<E, CT, CK extends Column<CT>> {
readonly table: TableExpression<E>
readonly column: CK
alias?: string
constructor(table: TableExpression<E>, column: CK, alias?: string) {
this.table = table
this.column = column
this.alias = alias
}
}
type Table<E> = {
[P in keyof E]: E[P] extends (infer U) ? Column<U> : never
}
type TableQuery<E> = {
[P in keyof E]: E[P] extends Column<(infer CT)> ? ColumnExpression<E, CT, E[P]> : never
}
export class TableExpression<E> {
readonly table: Table<E>
alias?: string
constructor(table: Table<E>, alias?: string) {
this.table = table
this.alias = alias
}
}
function toTable<E>(target: E): Table<E> {
let result = {} as Table<E>
for (const k in target) {
result[k] = new Column(target[k])
}
return result
}
function toTableExpression<E>(target: E): TableExpression<E> {
const table = toTable(target)
return new TableExpression(table)
}
function toTableFilter<E>(target: TableExpression<E>): TableQuery<E> {
let result = {} as TableQuery<E>
let table = target.table
for (const k in table) {
result[k] = new ColumnExpression(target, table[k])
}
return result
}
class Test {
id: number
name: string
createdAt: Date
createdById: number
}
let contentTable = toTable(new Test())
let contentFilter = toTableFilter(new TableExpression(contentTable))
contentTable.id.base
contentTable.name.base
第 56 行弹出确切的错误:
result[k] = new ColumnExpression(target, table[k])
错误:
(56,46): error TS2345: Argument of type 'Table<E>[keyof E]' is not assignable to parameter of type 'Column<{}>'.
Type 'Column<E[keyof E]>' is not assignable to type 'Column<{}>'.
Type 'E[keyof E]' is not assignable to type '{}'.
1:57:46 PM - Compilation complete. Watching for file changes.
在 TS 2.6 中,我根据索引类型访问(根据其他人对 SO 的建议)为 ColumnExpression
使用了不同的类型定义,作为参考,它被定义为:
type TableQuery<TK extends TableLike> = {
[P in keyof TK]: Column.ColumnExpression<TK, TK[P]['base'], TK[P]>
}
TK[P]['base']
允许我访问基础列类型,但这种方法从 TS 2.7 开始不再有效。目前还不清楚它是否是一个错误。我已经通读了一些看似相关但 none 解决这个确切问题的 GH 问题。我希望 2.8 中引入的条件类型能让我更干净地解决这个问题,但到目前为止,运气并不好。
如有任何想法,我们将不胜感激。
正如我所说,您的类型似乎已损坏,我不知道它们应该是什么。 如果您的代码在运行时工作(是吗?)那么下面的代码不会产生错误,似乎与您在运行时所做的一致,并且不使用条件类型(所以应该使用 TS2.6):
export class Column<T> {
readonly base: T
constructor(base: T) {
this.base = base
}
}
// remove CT type, it can be calculated as CK['base'] if needed
export class ColumnExpression<E, CK extends Column<any>> {
// type CT = CK['base']
readonly table: TableExpression<E>
readonly column: CK
alias?: string
constructor(table: TableExpression<E>, column: CK, alias?: string) {
this.table = table
this.column = column
this.alias = alias
}
}
// no need for conditional types, reduces to this:
type Table<E> = {
[P in keyof E]: Column<E[P]>
}
// no need for conditional types, reduces to this:
type TableQuery<E extends Table<any>> = {
[P in keyof E]: ColumnExpression<E, E[P]>
}
export class TableExpression<E> {
readonly table: Table<E>
alias?: string
constructor(table: Table<E>, alias?: string) {
this.table = table
this.alias = alias
}
}
function toTable<E>(target: E): Table<E> {
let result = {} as Table<E>
for (const k in target) {
result[k] = new Column(target[k])
}
return result
}
function toTableExpression<E>(target: E): TableExpression<E> {
const table = toTable(target)
return new TableExpression(table)
}
// this is the real output of toTableFilter();
// note the difference between TableThing<E> and TableQuery<E>:
type TableThing<E> = {
[P in keyof E]: ColumnExpression<E, Column<E[P]>>
}
function toTableFilter<E>(target: TableExpression<E>): TableThing<E> {
let result = {} as TableThing<E>;
let table = target.table
for (const k in table) {
const z = new ColumnExpression(target, table[k])
result[k] = z
}
return result
}
class Test {
id!: number
name!: string
createdAt!: Date
createdById!: number
}
let contentTable = toTable(new Test())
let contentFilter = toTableFilter(new TableExpression(contentTable))
contentTable.id.base
contentTable.name.base
所有类型检查都应该发出与您问题中有问题的代码相同的 JavaScript。老实说,我不确定代码是否在运行时执行了它应该执行的操作,或者 TableThing<E>
实际上 意味着 。我认为这可能取决于您自己的理解。
希望对您有所帮助。祝你好运!
在遇到 TS 2.6 中的问题后,我一直在试验 TypeScript 2.8 的条件类型,但我 运行 遇到了一个我不理解的错误,需要一些帮助:
这个例子涉及到这个问题。
export class Column<T> {
readonly base: T
constructor(base: T) {
this.base = base
}
}
export class ColumnExpression<E, CT, CK extends Column<CT>> {
readonly table: TableExpression<E>
readonly column: CK
alias?: string
constructor(table: TableExpression<E>, column: CK, alias?: string) {
this.table = table
this.column = column
this.alias = alias
}
}
type Table<E> = {
[P in keyof E]: E[P] extends (infer U) ? Column<U> : never
}
type TableQuery<E> = {
[P in keyof E]: E[P] extends Column<(infer CT)> ? ColumnExpression<E, CT, E[P]> : never
}
export class TableExpression<E> {
readonly table: Table<E>
alias?: string
constructor(table: Table<E>, alias?: string) {
this.table = table
this.alias = alias
}
}
function toTable<E>(target: E): Table<E> {
let result = {} as Table<E>
for (const k in target) {
result[k] = new Column(target[k])
}
return result
}
function toTableExpression<E>(target: E): TableExpression<E> {
const table = toTable(target)
return new TableExpression(table)
}
function toTableFilter<E>(target: TableExpression<E>): TableQuery<E> {
let result = {} as TableQuery<E>
let table = target.table
for (const k in table) {
result[k] = new ColumnExpression(target, table[k])
}
return result
}
class Test {
id: number
name: string
createdAt: Date
createdById: number
}
let contentTable = toTable(new Test())
let contentFilter = toTableFilter(new TableExpression(contentTable))
contentTable.id.base
contentTable.name.base
第 56 行弹出确切的错误:
result[k] = new ColumnExpression(target, table[k])
错误:
(56,46): error TS2345: Argument of type 'Table<E>[keyof E]' is not assignable to parameter of type 'Column<{}>'.
Type 'Column<E[keyof E]>' is not assignable to type 'Column<{}>'.
Type 'E[keyof E]' is not assignable to type '{}'.
1:57:46 PM - Compilation complete. Watching for file changes.
在 TS 2.6 中,我根据索引类型访问(根据其他人对 SO 的建议)为 ColumnExpression
使用了不同的类型定义,作为参考,它被定义为:
type TableQuery<TK extends TableLike> = {
[P in keyof TK]: Column.ColumnExpression<TK, TK[P]['base'], TK[P]>
}
TK[P]['base']
允许我访问基础列类型,但这种方法从 TS 2.7 开始不再有效。目前还不清楚它是否是一个错误。我已经通读了一些看似相关但 none 解决这个确切问题的 GH 问题。我希望 2.8 中引入的条件类型能让我更干净地解决这个问题,但到目前为止,运气并不好。
如有任何想法,我们将不胜感激。
正如我所说,您的类型似乎已损坏,我不知道它们应该是什么。 如果您的代码在运行时工作(是吗?)那么下面的代码不会产生错误,似乎与您在运行时所做的一致,并且不使用条件类型(所以应该使用 TS2.6):
export class Column<T> {
readonly base: T
constructor(base: T) {
this.base = base
}
}
// remove CT type, it can be calculated as CK['base'] if needed
export class ColumnExpression<E, CK extends Column<any>> {
// type CT = CK['base']
readonly table: TableExpression<E>
readonly column: CK
alias?: string
constructor(table: TableExpression<E>, column: CK, alias?: string) {
this.table = table
this.column = column
this.alias = alias
}
}
// no need for conditional types, reduces to this:
type Table<E> = {
[P in keyof E]: Column<E[P]>
}
// no need for conditional types, reduces to this:
type TableQuery<E extends Table<any>> = {
[P in keyof E]: ColumnExpression<E, E[P]>
}
export class TableExpression<E> {
readonly table: Table<E>
alias?: string
constructor(table: Table<E>, alias?: string) {
this.table = table
this.alias = alias
}
}
function toTable<E>(target: E): Table<E> {
let result = {} as Table<E>
for (const k in target) {
result[k] = new Column(target[k])
}
return result
}
function toTableExpression<E>(target: E): TableExpression<E> {
const table = toTable(target)
return new TableExpression(table)
}
// this is the real output of toTableFilter();
// note the difference between TableThing<E> and TableQuery<E>:
type TableThing<E> = {
[P in keyof E]: ColumnExpression<E, Column<E[P]>>
}
function toTableFilter<E>(target: TableExpression<E>): TableThing<E> {
let result = {} as TableThing<E>;
let table = target.table
for (const k in table) {
const z = new ColumnExpression(target, table[k])
result[k] = z
}
return result
}
class Test {
id!: number
name!: string
createdAt!: Date
createdById!: number
}
let contentTable = toTable(new Test())
let contentFilter = toTableFilter(new TableExpression(contentTable))
contentTable.id.base
contentTable.name.base
所有类型检查都应该发出与您问题中有问题的代码相同的 JavaScript。老实说,我不确定代码是否在运行时执行了它应该执行的操作,或者 TableThing<E>
实际上 意味着 。我认为这可能取决于您自己的理解。
希望对您有所帮助。祝你好运!