firebase / firebase/firebase-admin-node
type ChildUpdateFields within type UpdateData does not play nicely with nested interfaces
- 主要语言
- 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:

**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.

#### 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:
贡献指南
调研方向
先从 ChildUpdateFields 的定义及其在 UpdateData 中的使用开始,然后使用所述的 TypeScript 和 firebase-admin 设置复现 issue 中的 UserSuccess 和 UserFail 示例。当嵌套的接口字段能够接受诸如 "name.first" 的点号更新,并在没有报告的类型错误的情况下提供相应的 IDE 提示时,即表示完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- firebase, typescript
- 领域
- databases
- Issue 类型
- 缺陷
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100