Last active
October 23, 2024 15:26
-
-
Save belgattitude/1d797ffab436bab09a209acdea8a3400 to your computer and use it in GitHub Desktop.
typescript-issue-with-async-discriminated-union
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Compilable, InferResult, Kysely } from 'kysely'; | |
type QueryResultSuccess<T> = { | |
success: true; | |
data: T; | |
}; | |
type QueryResultError = { | |
success: false; | |
errorMsg: string; | |
}; | |
type QueryResult<T> = QueryResultSuccess<T> | QueryResultError; | |
type AsyncQueryResult<T> = Promise<QueryResult<T>>; | |
type DB = { | |
product: { | |
id: number; | |
name: string; | |
}; | |
}; | |
class Datasource<TDatabase = DB> { | |
constructor(public kysely: Kysely<TDatabase>) {} | |
query = async <TFn extends () => any, TData = ReturnType<TFn>>( | |
fn: TFn | |
): AsyncQueryResult<TData> => { | |
return this.createQueryResultSuccess<TData>(fn()); | |
}; | |
queryKysely = async < | |
TQuery extends Compilable<unknown>, | |
TData = InferResult<TQuery>, | |
>( | |
query: TQuery | |
): AsyncQueryResult<TData> => { | |
try { | |
const r = await this.kysely.executeQuery(query); | |
return this.createQueryResultSuccess<TData>(r.rows as TData); | |
} catch (err) { | |
return this.createQueryResultError(err as Error); | |
} | |
}; | |
protected createQueryResultSuccess = <T>(data: T): QueryResultSuccess<T> => { | |
return { | |
success: true, | |
data: data, | |
}; | |
}; | |
protected createQueryResultError = (err: Error): QueryResultError => { | |
return { | |
success: false, | |
errorMsg: err.message, | |
}; | |
}; | |
} | |
type Product = { | |
id: number; | |
name: string; | |
description: string; | |
}; | |
class Repo { | |
constructor(private ds: Datasource) {} | |
search = async (): AsyncQueryResult<Product[]> => { | |
// ts-expect-error shoudl give an error cause id aren't the same types | |
type IncompleteProduct = { | |
id: number; | |
name: string; | |
}; | |
const incompleteProduct: IncompleteProduct = { | |
id: 1, | |
name: 'Incomplete Product', | |
}; | |
const getIncompleteProducts = (): IncompleteProduct[] => { | |
return [incompleteProduct]; | |
}; | |
return this.ds.query(getIncompleteProducts); | |
const a = await this.ds.query(getIncompleteProducts); | |
if (a.success) { | |
const _z = a.data[0]?.id; | |
} | |
return a; | |
}; | |
searchKysely = async (): AsyncQueryResult<Product[]> => { | |
const query = this.ds.kysely.selectFrom('product').select(['id', 'name']); | |
const a = await this.ds.queryKysely(query); | |
return a; | |
// return await this.ds.queryKysely(query); | |
// return this.ds.queryKysely(query); | |
}; | |
} | |
const kysely = {} as unknown as Kysely<DB>; | |
const repo = new Repo(new Datasource(kysely)); | |
const testTypes = async () => { | |
const result = await repo.search(); | |
const _idOrErrMessage = result.success | |
? result.data[0]?.id | |
: result.error.messsage; | |
const result2 = await repo.searchKysely(); | |
const _idOrErrMessage2 = result2.success | |
? result2.data[0]?.id | |
: result2.error.messsage; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment