firebase / firebase/firebase-admin-node

type ChildUpdateFields within type UpdateData does not play nicely with nested interfaces

未关闭
#2,022 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
needs-triage
主要语言
TypeScript
星标
1.7k
派生
419
平均合并
3 天 10 小时
30 天内合并 PR
16

描述

### Describe your environment

* Operating System version: MacOS Monterey 12.6
* Firebase SDK version: 11.19.0
* Firebase Product: Firebase Admin
* Node.js version: 16.15.0
* NPM version: 8.5.5

### Describe the problem

#### Steps to reproduce:

Create a simple environment to work with:
```bash
> npm init # go through the init steps
> npm install typescript # currently 4.9.4
> npm install firebase-admin # currently 11.4.0
```

#### Relevant Code:

Create a typescript file with the following:

```ts
interface UserSuccess {
name: {
first: string;
last: string;
};
}

interface UserFail {
name: Name;
}

interface Name {
first: string;
last: string;
}
```

Note how both `UserSuccess` and `UserFail` are technically identical in structure.

When using the `UpdateData` type, you are able to traverse interface objects to update a specific field within Firebase. For example, something like this:
`docRef.update({ "name.first": "John" });`

However, when working with an interface that has a nested Interface object, `UpdateData`, or more specifically, `ChildUpdateFields` within `UpdateData`, fails to generate the new expected `type` whenever there are interfaces with other interfaces.

**Success:**
```ts
const user: FirebaseFirestore.UpdateData = {
"name.first": "John",
};
```
The IDE even shows a list of helpful and expected suggestions:
image

**Failure:**
```ts
const user: FirebaseFirestore.UpdateData = {
"name.first": "John", // ERROR
};
```
This produces the following error:
```
Type '{ "name.first": string; }' is not assignable to type '{ name?: FieldValue | { first?: string | FieldValue | undefined; last?: string | FieldValue | undefined; } | undefined; }'.
Object literal may only specify known properties, and '"name.first"' does not exist in type '{ name?: FieldValue | { first?: string | FieldValue | undefined; last?: string | FieldValue | undefined; } | undefined; }'.
```
Secondly, the IDE does not show the intersected keys like above in the success state.
image

#### Possible Solution
Look at the `ChildUpdateFields` type.
```ts
export type ChildUpdateFields =
V extends Record
? AddPrefixToKeys>
: never;
```

Change `unknown` to `any`:
```ts
export type ChildUpdateFields =
V extends Record
? AddPrefixToKeys>
: never;
```

Suddenly, all problems described above are fixed. On top of that, the IDE also shows helpful and expected suggestions.

`UserFail` now behaves the same as `UserSuccess`:
```ts
const user: FirebaseFirestore.UpdateData = {
"name.first": "John", // no more errors
};
```
Proper suggestions are listed in the IDE:
image

贡献指南

打开贡献指南

调研方向

先从 ChildUpdateFields 的定义及其在 UpdateData 中的使用开始,然后使用所述的 TypeScript 和 firebase-admin 设置复现 issue 中的 UserSuccess 和 UserFail 示例。当嵌套的接口字段能够接受诸如 "name.first" 的点号更新,并在没有报告的类型错误的情况下提供相应的 IDE 提示时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
firebase, typescript
领域
databases
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。