nic*_*ckf 11 node.js typescript typescript-typings
Node 内置 IncomingMessage((req, res, next)参数中的 req 类型)的绝对类型定义已定义url为 nullable。以下是定义文件的片段:
// @types/node/index.d.ts
declare module "http" {
export interface IncomingMessage {
/**
* Only valid for request obtained from http.Server.
*/
url?: string;
}
}
Run Code Online (Sandbox Code Playgroud)
正如评论所说,这是因为此属性仅在您从 http.Server 获取此 IncomingMessage 的实例时才有效。在其他用途中它不存在,因此,它可以为空。
但是,就我而言,我知道我只能从 http.Server 获取这些实例,因此我无法在没有额外保护的情况下访问该属性,这有点烦人。
import { IncomingMessage, ServerResponse } from 'http';
function someMiddleware(req: IncomingMessage, res: ServerResponse, next: Function) {
const myStr: string = req.url; // bzzzt.
// Argument of type 'string | undefined' is not
// assignable to parameter of type 'string'.
}
Run Code Online (Sandbox Code Playgroud)
值得一提的是,我将 TS 2.0.3 与 一起使用strictNullChecks,但在Typescript Playground上未启用。
这是问题。是否可以在我的应用程序中覆盖该定义,使其url不可为空?
这是我已经尝试过的……将其添加到我的一个文件中:
declare module 'http' {
interface IncomingMessage {
url: string;
}
}
Run Code Online (Sandbox Code Playgroud)
...但是这是不允许的:“后续变量声明必须具有相同的类型”。这在文档中进行了解释。
到目前为止,我唯一能想到的就是创建我自己的模块,该模块导入、扩展然后导出接口:
// /src/http.ts
import { IncomingMessage as OriginalIM } from 'http';
export interface IncomingMessage extends OriginalIM {
url: string;
}
// src/myapp.ts
import { IncomingMessage } from './http'; // <-- local def
function someMiddleware(req: IncomingMessage) {
const str: string = req.url; // all good
}
Run Code Online (Sandbox Code Playgroud)
所以,这有效,但似乎错了。
Cyb*_*igy 22
在您的示例案例中,这很容易,因为您想摆脱 ALL undefined,因此使用Required实用程序类型。
interface IncomingMessage { url?: string; }
type ValidMessage = Required<IncomingMessage>;
Run Code Online (Sandbox Code Playgroud)
ValidMessage 将具有所有属性required。
但对于那些来这里了解如何摆脱 ALL 的人null,您可以使用此自定义实用程序类型。
export type NonNullableFields<T> = {
[P in keyof T]: NonNullable<T[P]>;
};
interface IncomingMessage { url: string | null; }
type ValidMessage = NonNullableFields<IncomingMessage>;
Run Code Online (Sandbox Code Playgroud)
ValidMessage 将具有所有属性not null。
对于那些来这里了解如何仅删除null特定字段的人,您可以使用这些自定义实用程序类型。
export type NonNullableFields<T> = {
[P in keyof T]: NonNullable<T[P]>;
};
export type NonNullableField<T, K extends keyof T> = T &
NonNullableFields<Pick<T, K>>;
interface IncomingMessage { url: string | null; }
type ValidMessage = NonNullableField<IncomingMessage, 'url'>;
Run Code Online (Sandbox Code Playgroud)
ValidMessage 将具有属性url not null。
nic*_*ckf 16
所以我找到了一个稍微不那么hacky的解决方案。
TypeScript 2.0 还添加了一个非空断言运算符:!
function someMiddleware(req: IncomingMessage) {
const str1: string = req.url; // error, can't assign string | undefined to string
const str2: string = req.url!; // works
}
Run Code Online (Sandbox Code Playgroud)
就我而言,它仍然有点烦人,因为有许多不同的文件需要访问此属性,因此在许多地方都使用了此非空断言。
小智 10
从 TypeScript 2.1 开始,您可以使用查找类型来访问接口属性。
IncomingMessage['url'] // string | undefined
Run Code Online (Sandbox Code Playgroud)
您可以将其与NonNullable适合您的用例结合使用。
NonNullable<IncomingMessage['url']> // string
Run Code Online (Sandbox Code Playgroud)
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
这是定义实用程序类型的解决方案RequiredProperties:
type RequiredProperties<T, P extends keyof T> = Omit<T, P> & Required<Pick<T, P>>;
Run Code Online (Sandbox Code Playgroud)
用法示例:
type Foo = {
a?: any;
b?: any;
c?: any;
};
type Bar = RequiredProperties<Foo, 'a' | 'b'>;
const bar1: Bar = { a: 1, b: 2, c: 3 };
const bar2: Bar = { b: 2, c: 3 }; // fails because `a` is now required
const bar3: Bar = { c: 3 }; // fails because both `a` and `b` are missing
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11387 次 |
| 最近记录: |