Typescript 在启用严格空检查的情况下强制分配未定义的?

Typescript 在启用严格空检查的情况下强制分配未定义的?,typescript,Typescript,我正在考虑为我一直在处理的TypeScript项目启用strictNullChecks标志,但它会产生许多编译器错误。其中一些是我真正需要检查的边缘案例,但其中许多属于特定模式 type BusinessObject = { id: string; name: string; requiredValue: number; // ... } class DataStore { // ... public addItem(item: BusinessObject): Pro

我正在考虑为我一直在处理的TypeScript项目启用
strictNullChecks
标志,但它会产生许多编译器错误。其中一些是我真正需要检查的边缘案例,但其中许多属于特定模式

type BusinessObject = {
  id: string;
  name: string;
  requiredValue: number;
  // ...
}

class DataStore {
  // ...
  public addItem(item: BusinessObject): Promise<string>;
  public getItem(id: string): Promise<BusinessObject>;
}

function consumeData(store: DataStore){
  store.addItem({name:"one", requiredValue:1});
  store.getItem("two").then(item => console.log(item.id));
}
类型BusinessObject={
id:字符串;
名称:字符串;
requiredValue:数字;
// ...
}
类数据存储{
// ...
公共附加项(项目:BusinessObject):承诺;
public-getItem(id:string):承诺;
}
函数数据(存储:数据存储){
addItem({name:“one”,requiredValue:1});
然后(item=>console.log(item.id));
}
问题在于
id
属性是由后台数据库创建的,因此在创建新项目时,它只是“可选的”。如果我将
id
属性设置为必需(否
?:
),则调用
addItem
时会出现编译器错误。但是如果我将ID属性设置为可选,那么对它的每个引用都必须包含一个保护或(
item.ID!

到目前为止,我能想到的最不坏的解决方案是将传递给
addItem
的参数转换为
any
,但这会禁用对
BusinessObject
的其他属性的检查,因此这不是一个好的解决方案。我所希望的是一种类似于非空断言运算符的操作,它允许我断言空赋值是可以的,尽管类型声明说它不是:类似于
store.addItem({id:undefined!,name:“one”,requiredValue:1})


我还希望有更好/更一致的方式来描述此模式。

您可以有两种类型,一种表示创建时的对象,另一种表示保存的对象

type NewBusinessObject = {
    id?: string;
    name: string;
    requiredValue: number;
    // ...
}
type BusinessObject = NewBusinessObject & {
    id: string
}

declare class DataStore {
    // ...
    public addItem(item: NewBusinessObject): Promise<string>;
    public getItem(id: string): Promise<BusinessObject>;
}

function consumeData(store: DataStore) {
    store.addItem({ name: "one", requiredValue: 1 });
    store.getItem("two").then(item => console.log(item.id));
}
类型NewBusinessObject={
id?:字符串;
名称:字符串;
requiredValue:数字;
// ...
}
输入BusinessObject=NewBusinessObject&{
id:字符串
}
声明类数据存储{
// ...
公共附加项(项目:NewBusinessObject):承诺;
public-getItem(id:string):承诺;
}
函数数据(存储:数据存储){
addItem({name:“one”,requiredValue:1});
然后(item=>console.log(item.id));
}

您可以有两种类型,一种表示创建时的对象,另一种表示保存的对象

type NewBusinessObject = {
    id?: string;
    name: string;
    requiredValue: number;
    // ...
}
type BusinessObject = NewBusinessObject & {
    id: string
}

declare class DataStore {
    // ...
    public addItem(item: NewBusinessObject): Promise<string>;
    public getItem(id: string): Promise<BusinessObject>;
}

function consumeData(store: DataStore) {
    store.addItem({ name: "one", requiredValue: 1 });
    store.getItem("two").then(item => console.log(item.id));
}
类型NewBusinessObject={
id?:字符串;
名称:字符串;
requiredValue:数字;
// ...
}
输入BusinessObject=NewBusinessObject&{
id:字符串
}
声明类数据存储{
// ...
公共附加项(项目:NewBusinessObject):承诺;
public-getItem(id:string):承诺;
}
函数数据(存储:数据存储){
addItem({name:“one”,requiredValue:1});
然后(item=>console.log(item.id));
}

我刚刚意识到,有一个操作符或多或少都像我描述的那样工作:

store.addItem({ id: undefined as any, name: "one", requiredValue: 1 });

我仍然希望有更好的长期解决方案,如Titian的建议,但这至少是一种选择。

我刚刚意识到,有一个运营商或多或少都能像我描述的那样工作:

store.addItem({ id: undefined as any, name: "one", requiredValue: 1 });

我仍然希望有更好的长期解决方案,如Titian的建议,但这至少是一个选择。

避免错误的一个简单方法是将
附加项的定义更改为:

public addItem(item: Partial<BusinessObject>): Promise<string>
在typescript中有一些类似的建议(例如,请参阅),因此您的代码有望在将来得到简化

这一期有很多内容,为了节省您的阅读时间,以下是一些似乎有效的内容(另见第19569期):

export type Diff=({[P in T]:P}&
{[P in U]:never}&{[x:string]:never}[T];
导出类型省略=拾取;
类型BusinessObject={
id:字符串;
名称:字符串;
requiredValue:数字;
// ...
}
类数据存储{
// ...
公共附加项(项目:省略):承诺{
返回承诺。解析('foo')};
公共getItem(id:string):承诺{
返回Promise.resolve({}与BusinessObject一样);
};
}
函数数据(存储:数据存储){
addItem({name:“one”,requiredValue:1});
然后(item=>console.log(item.id));
}

(为
addItem
getItem
添加了虚拟主体代码,以使编译器满意,忽略它。)

避免错误的一个简单方法是将
addItem
的定义更改为:

public addItem(item: Partial<BusinessObject>): Promise<string>
在typescript中有一些类似的建议(例如,请参阅),因此您的代码有望在将来得到简化

这一期有很多内容,为了节省您的阅读时间,以下是一些似乎有效的内容(另见第19569期):

export type Diff=({[P in T]:P}&
{[P in U]:never}&{[x:string]:never}[T];
导出类型省略=拾取;
类型BusinessObject={
id:字符串;
名称:字符串;
requiredValue:数字;
// ...
}
类数据存储{
// ...
公共附加项(项目:省略):承诺{
返回承诺。解析('foo')};
公共getItem(id:string):承诺{
返回Promise.resolve({}与BusinessObject一样);
};
}
函数数据(存储:数据存储){
addItem({name:“one”,requiredValue:1});
然后(item=>console.log(item.id));
}

(为
addItem
getItem
添加了虚拟主体代码以使编译器满意,请忽略这一点。)

这是我第一次看到提到的
Partial
,非常有帮助。谢谢@编码者我编辑了我的答案,在长时间的讨论中加入了对
省略的建议定义。这是我第一次看到提到的
部分
,非常有帮助。谢谢@编码者我编辑了我的答案,在长时间的讨论中加入了建议的
省略
的定义。