Summary: Generating Types for Raw Return Types in TypeORM
Hello, I'm working with TypeORM and have a question about handling raw return types. When using getRawOne and getRawMany functions, the return includes strings composed of class names and properties, which are concatenated with an underscore ('_').
For example:
export class TestUser {
id: number;
name: string;
verified: boolean;
}
const userRepository = getRepository(TestUser);
// getRawOne is not support type. just return any type. I want to disclose this return type.
const loaedRawTestUser = await userRepository.createQueryBuilder('testUser')
.addSelect('COUNT(*()', 'myAliasForAllUserCount')
.getRawOne();
/**
* {
* testUser_id: number;
* testUser_name: string;
* testUser_verified: boolean;
* }
*/
console.log(loaedRawUser);
The issue comprises three parts:
The first part has been resolved.
I've implemented a camelCase to snake_case type inferer as follows:
export type CamelCaseToSnakeCase<
T extends string,
Joiner extends '' | '_' = ''
> = T extends `${infer Character}${infer Rest}`
? Character extends Uppercase<Character>
? `${Joiner}${Lowercase<Character>}${CamelCaseToSnakeCase<Rest, '_'>}`
: `${Character}${CamelCaseToSnakeCase<Rest, '_'>}`
: '';
Is there something way?
Additional Requirements if it can be.
When TestUser class has method like this:
export class TestUser {
id: number;
name: string;
verified: boolean;
getNameIfVerified(): {
return this.verified ? this.name : 'not verified'
}
}
const typeormRawColumTestSample: Partial<TypeORMRawColumns<TestUser, 'TestUser'>> = {
testUser_id: 1,
// when testUser_id: '1' should be error.
testUser__get_name_if_verified // should be error.
}
How can I exclude methods from a Type in TypeScript
I've partially resolved the second issue, but it's not completely solved yet.
/**
* Not yet typescript is not support inferring class name from Type T.
* So, I regard programmer must input entity class name as hardcoding.
*/
export type TypeORMRawColumns<
Entity,
EntityClassName extends string,
ConvertedPropertyToSnake = `${Uncapitalize<EntityClassName>}_${CamelCaseToSnakeCase<
Extract<keyof Entity, string>
>}`,
ValueType = Entity[keyof Entity]
> = {
[key in Extract<ConvertedPropertyToSnake, string>]: ValueType;
};
// Second parameter is hard coded for class name.
const test1: TypeORMRawColumns<TestUser, 'TestUser'> = {
testUser_id: 1,
testUser_name: 'john',
testUser_verified: true
};
// But by union type, it is not safe from other property type.
// Expected error but it is not.
const test2: TypeORMRawColumns<TestUser, 'TestUser'> = {
testUser_id: 'it is not type-safe. Because of ValueOf is union type of Entity properties.',
// like number | string | boolean
testUser_name: 'john',
testUser_verified: true
};