使用 Fetch with Typescript 进行类型推断
Type Inferance using Fetch with Typescript
我使用 Typescript 编写了一个 Fetch 包装器来获取我的 API。我想,当我从我的 API 取回我的数据时,从“任何”类型到我的例如:“用户”类型。
我给你贴了一个 link 作为我的 codesandebox : https://codesandbox.io/s/react-query-error-rkmv1
当我 console.log 在 onSuccess 回调中(甚至直接在获取中)时,即使 Typescript 编译器没有报错,我也可以将获取的数据用作“用户”,如果我记录这个用户,它不是真正的用户。这是一个我可以“作为”用户使用的对象,但不能作为“用户”使用。
我可以这样保留它,因为最终它起作用了,我的结果是典型的,但我担心它会带来其他我没有想到的问题。
谢谢!
您实际上是在使用和界面。在运行时打字稿接口,或任何自定义类型,不存在,只是一个普通对象,打字稿的签名。在实际的 JavaScript 代码中只有 classes 是“可见的”,但是您应该使用 new
运算符实例化 class。
正如您所说,“它带来了我没有想到的其他问题”。解决方案是在界面之外再创建一个class,这样就可以与之交互了。
export interface IUserData {
// id: number; // ID should not be part of the data
name: string;
firstName: string;
email: string;
password?: string;
}
export class User {
public readonly attributes: IUserData;
constructor(data: Partial<IUserData>, public readonly id?: number) {
// validate and initialize default values of attributes
this.attributes = { /* all keys with default values*/ };
}
}
然后,您可以使用该接口作为响应的签名,并使用 const model = new User(response.data, response.id)
创建一个新实例。这样您就可以将“功能”添加到 class 以在实例之间共享。 model.attributes
具有可供使用的原始属性。可以创建getters/setters直接访问属性等
Partial<T>
is an utility type of typescript core to tell an object has attributes of T, but optional. This is useful if you are working with PATCH for only email
, for example.
所以我注意到,如果您希望 IDE 反映函数的 return,则需要显式定义函数的 return,让我们使用 get 函数您在 link...
中提供的
function get<T>(input: Request | string, init?): Promise<Partial<T>> { // so the return is defined here
const token = localStorage.getItem(localStorageKey);
const requestInit = {
method: "GET",
...init
};
if (token) {
requestInit.headers = {
Authorization: `Bearer ${token}`,
...requestInit.headers
};
}
return fetch(apiUrl + input, requestInit)
.then(handleResponse)
.then((res) => res.json())
.then((data) => data as T);
}
试一试...谢谢
我使用 Typescript 编写了一个 Fetch 包装器来获取我的 API。我想,当我从我的 API 取回我的数据时,从“任何”类型到我的例如:“用户”类型。
我给你贴了一个 link 作为我的 codesandebox : https://codesandbox.io/s/react-query-error-rkmv1
当我 console.log 在 onSuccess 回调中(甚至直接在获取中)时,即使 Typescript 编译器没有报错,我也可以将获取的数据用作“用户”,如果我记录这个用户,它不是真正的用户。这是一个我可以“作为”用户使用的对象,但不能作为“用户”使用。
我可以这样保留它,因为最终它起作用了,我的结果是典型的,但我担心它会带来其他我没有想到的问题。
谢谢!
您实际上是在使用和界面。在运行时打字稿接口,或任何自定义类型,不存在,只是一个普通对象,打字稿的签名。在实际的 JavaScript 代码中只有 classes 是“可见的”,但是您应该使用 new
运算符实例化 class。
正如您所说,“它带来了我没有想到的其他问题”。解决方案是在界面之外再创建一个class,这样就可以与之交互了。
export interface IUserData {
// id: number; // ID should not be part of the data
name: string;
firstName: string;
email: string;
password?: string;
}
export class User {
public readonly attributes: IUserData;
constructor(data: Partial<IUserData>, public readonly id?: number) {
// validate and initialize default values of attributes
this.attributes = { /* all keys with default values*/ };
}
}
然后,您可以使用该接口作为响应的签名,并使用 const model = new User(response.data, response.id)
创建一个新实例。这样您就可以将“功能”添加到 class 以在实例之间共享。 model.attributes
具有可供使用的原始属性。可以创建getters/setters直接访问属性等
Partial<T>
is an utility type of typescript core to tell an object has attributes of T, but optional. This is useful if you are working with PATCH for only
所以我注意到,如果您希望 IDE 反映函数的 return,则需要显式定义函数的 return,让我们使用 get 函数您在 link...
中提供的function get<T>(input: Request | string, init?): Promise<Partial<T>> { // so the return is defined here
const token = localStorage.getItem(localStorageKey);
const requestInit = {
method: "GET",
...init
};
if (token) {
requestInit.headers = {
Authorization: `Bearer ${token}`,
...requestInit.headers
};
}
return fetch(apiUrl + input, requestInit)
.then(handleResponse)
.then((res) => res.json())
.then((data) => data as T);
}
试一试...谢谢