如何在NestJS中使用TypeORM正确地输入Postgres数据库的返回值?

huangapple go评论55阅读模式
英文:

How can I correctly type the return value from a Postgres database in TypeORM with NestJS?

问题

# 如何正确地输入从postgres数据库返回的值

有人可以解释一下这一点吗?我在使用PostgreSQL、Nest和TypeORM方面还很新手,我想创建一个基本的CRUD应用程序。我对在TypeORM中进行输入方面有一个问题。

我的用户实体:

```typescript
@Entity('user')
export class UserEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ unique: true })
  email: string;

  @Column({
    type: 'varchar',
  })
  name: string;

  @Column({
    type: 'varchar',
  })
  password: string;

  @Column({
    nullable: true,
    type: 'varchar',
    default: () => 'NULL',
  })
  refreshToken: string;
}

我的用户服务:

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(UserEntity)
    private usersRepository: Repository<UserEntity>,
  ) {}

  createUser(createUserDto: SignUpDto) {
    return this.usersRepository.save(createUserDto);
  }

  findAllUsers() {
    return this.usersRepository.find({
      select: ['id', 'email', 'name'],
    });
  }

  findUserById(id: number) {
    return this.usersRepository
      .createQueryBuilder('user')
      .select([
        'user.id',
        'user.email',
        'user.name',
      ])
      .where('user.id= :userId', { userId: id })
      .getOne();
  }

  findUserByEmail(email: string) {
    return this.usersRepository.findOneBy({ email });
  }
}

FindUserById是一个外部方法(有一个控制器方法调用它)。它返回一个具有不完整数据的用户,没有密码和refreshToken字段(我认为它们不应该暴露)。

FindUserByEmail是一个内部方法,被另一个服务(authService)使用。它返回完整的用户数据。

问题在于推断的返回类型在两种情况下都是Promise<UserEntity>,我不明白这怎么能适应这两个函数。

首先,我认为推断类型至少应该是Promise<UserEntity | null>。但它不是。

其次,我以为TypeORM会自动推断数据类型。问题是,TypeORM实际上能做到吗?如果不能,我应该如何正确地为返回值定义类型?创建多个不同的数据类型吗?使用Omit吗?通过添加可选字段来为UserEntity类型定义类型吗?我不明白。


<details>
<summary>英文:</summary>

# How to correctly type the value returned from the postgres database

Can anyone please explane this moment. I&#39;m new at postgresql, nest and typeorm, and i want to create primitive CRUD application. I have a question about typing at typeorm.

My User Entity:

@Entity('user')
export class UserEntity {
@PrimaryGeneratedColumn()
id: number;

@Column({ unique: true })
email: string;

@Column({
type: 'varchar',
})
name: string;

@Column({
type: 'varchar',
})
password: string;

@Column({
nullable: true,
type: 'varchar',
default: () => 'NULL',
})
refreshToken: string;
}


My UserService:

@Injectable()
export class UsersService {
constructor(
@InjectRepository(UserEntity)
private usersRepository: Repository<UserEntity>,
) {}

createUser(createUserDto: SignUpDto) {
return this.usersRepository.save(createUserDto);
}

findAllUsers() {
return this.usersRepository.find({
select: ['id', 'email', 'name'],
});
}

findUserById(id: number) {
return this.usersRepository
.createQueryBuilder('user')
.select([
'user.id',
'user.email',
'user.name',
])
.where('user.id= :userId', { userId: id })
.getOne();
}

findUserByEmail(email: string) {
return this.usersRepository.findOneBy({ email });
}
}


**`FindUserById`** is external method (there is a controller method that calls it) . It returns a user with incomplete data without password and refreshToken fields ( I don&#39;t think they should be exposed).  
**`FindUserByEmail`** is an internal method that is used by another service (`authService`). It returns the complete user data.

The problem is that the inferred return type is `Promise&lt;UserEntity&gt;` in both cases, and I don&#39;t see how that could fit both functions.

First, I think the inferred type should be at least `Promise&lt;UserEntity | null&gt;`. But it&#39;s not.

Second, I thought TypeORM would automatically infer the data type. The question is, can TypeORM actually do this? And if not, how do I correctly type return values then? Create multiple different data types? Use `Omit`? Type `UserEntity` by adding optional fields? I don&#39;t understand.

</details>


# 答案1
**得分**: 0

The problem is that the inferred return type is `Promise<UserEntity>` in both cases, and I don't see how that could fit both functions.
问题在于推断的返回类型在两种情况下都是`Promise<UserEntity>`,我不明白如何适应这两个函数。

First, I think the inferred type should be at least `Promise<UserEntity | null>`. But it's not.
首先,我认为推断的类型至少应该是`Promise<UserEntity | null>`。但它不是。

You're correct. The options are either it finds it in the db and resolves with `UserEntity`, or it doesn't find it and resolves with `null`.
你说得对。选项要么在数据库中找到它并解析为`UserEntity`,要么找不到并解析为`null`。

`UserEntity` is an object. Any object can be `null`. Therefore `UserEntity | null` is the same as just `UserEntity`.
`UserEntity` 是一个对象。任何对象都可以是 `null`。因此 `UserEntity | null` 和 `UserEntity` 是一样的。

Second, I thought TypeORM would automatically infer the data type. The question is, can TypeORM actually do this? And if not, how do I correctly type return values then? Create multiple different data types? Use Omit? Type UserEntity by adding optional fields? I don't understand.
其次,我以为 TypeORM 会自动推断数据类型。问题是,TypeORM 真的能做到吗?如果不能,那么如何正确地为返回值添加类型?创建多个不同的数据类型?使用 Omit?通过添加可选字段来为 UserEntity 添加类型?我不明白。

TypeORM infers the return type with the assumption that you return the full entity (don't do any `select`s). Since you know more than TypeORM when writing your `UsersService`, you're responsible for specifying more precise type information if you want to. `Partial`/`Omit`/`Pick` are good options for this.
TypeORM 推断返回类型的前提是你返回完整的实体(不要使用任何 `select`)。由于在编写 `UsersService` 时,你比 TypeORM 更了解情况,因此如果需要,你需要负责指定更精确的类型信息。`Partial`/`Omit`/`Pick` 都是这方面的好选项。

<details>
<summary>英文:</summary>

&gt; The problem is that the inferred return type is `Promise&lt;UserEntity&gt;` in both cases, and I don&#39;t see how that could fit both functions.
&gt; First, I think the inferred type should be at least `Promise&lt;UserEntity | null&gt;`. But it&#39;s not.

You&#39;re correct. The options are either it finds it in the db and resolves with `UserEntity`, or it doesn&#39;t find it and resolves with `null`.

`UserEntity` is an object. Any object can be `null`. Therefore `UserEntity | null` is the same as just `UserEntity`.

&gt; Second, I thought TypeORM would automatically infer the data type. The question is, can TypeORM actually do this? And if not, how do I correctly type return values then? Create multiple different data types? Use Omit? Type UserEntity by adding optional fields? I don&#39;t understand.

TypeORM infers the return type with the assumption that you return the full entity (don&#39;t do any `select`s). Since you know more than TypeORM when writing your `UsersService`, you&#39;re responsible for specifying more precise type information if you want to. `Partial`/`Omit`/`Pick` are good options for this.

</details>



huangapple
  • 本文由 发表于 2023年5月25日 19:51:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331960.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定