如何仅允许类中的字符串属性?

问题描述 投票:0回答:1
In

express

, the value of 
req.params
 is an object, which can only have string properties.

By default,

req.params

 is typed to be 
Record<string, string>
, which isn't really useful.我想向编译器提供键入信息,以便它知道预期的属性,而不是预期的。
我可以在许多方面做到这一点。我最终做的是创建一个抽象,使我可以使用类定义来定义
req.params
的形状。这很有用,因为我可以免费提供此类班,并且可以免费进行运行时验证。

此抽象接受课程并返回打字请求处理程序。沿着:

req.params
class-validator

问题是,我可以将参数类定义为具有任何属性,不仅是

declare function createRequestHandler<Params extends object>( paramsConstructor: new (...args: never) => Params, handler: express.RequestHandler<Params>, ): express.RequestHandler<Params>

或源自
class GetUserByIdParams {
  userId!: string
}

app.get('/users/:userId', createRequestHandler(GetUserByIdParams, (req) => {
  req.params.userId; // ✅ well-typed
}))
或从
string
衍生而来的,而且还具有复合对象 - 当然是,这是一个复合对象。

string

的运行时值不是什么。
number
是的,当我实际运行此代码时,我会从
boolean
中遇到验证错误,但是我也想在设计时有此约束。
我如何限制
req.params
仅具有字符串属性?
    

有两种方法:1)轻松而烦人,2)复杂而健壮。
easyand Toughing:索引签名

限制类属性为
class InvalidParams { userId!: number } app.get('/users/:userId', createRequestHandler(InvalidParams, (req) => { req.params.userId.toFixed(2); // ❌ method 'toFixed' doesn't exist, but no errors here }))

S的简便方法是添加索引签名:

class-validator

但是,再一次,没有人阻止开发人员不包括它:

Params
typescript constructor typescript-generics
1个回答
0
投票
索引签名可以通过the类型参数约束的微小变化来强制执行:从

string

class Params { [key: string]: string userId!: number // ✅ Error: Property 'userId' of type 'number' is not assignable to 'string' index type 'string' }

class Params {
  userId!: number // ❌ no errors
}

createRequestHandler

这使得不可避免地会使索引特征。但是索引签名具有其他不幸的功能:它们允许访问未知的属性:

extends object

与默认值相比,这种方法几乎没有更有用。 complex andRobust

一种更为复杂但更强大的方法是收集模型的属性,并评估它们都可以分配给
extends Record<string, string>
(含义,属性值是a的,或者是从
declare function createRequestHandler<Params extends Record<string, string>>(…): …
 
,例如字符串字面类型,或解决字符串值的枚举)。如果其属性中的任何一个比

class Params { userId!: number } createRequestHandler(Params, () => …) // ^^^^^^ // ✅ Error: Index signature for type 'string' is missing in type 'Params'
(例如
enum UserRole { Admin = 'Admin', User = 'User' } class Params { [key: string]: string userId!: string userRole!: UserRole } new Params().userId // ✅ string new Params().userRole // ✅ UserRole new Params().fooBar // ❌ string, no error new Params().literallyDoesNotExist // ❌ string, no error
Record<string, string>

)更通用的情况,这将使输入类无效。

操作员可以帮助使对象的所有属性的所有值结合:
string

简单类型的实用程序,该实用程序检查是否从另一种类型中派生出一种类型会看起来像这样:

string


comporting上述情况,此类型的实用程序返回
string
如果对象的至少一个属性比
string
string | number

要将其应用于

unknown
,请指示给定类构造一个仅具有
keyof

type ValuesOf<Obj extends object> = Obj[keyof Obj] 衍生属性的实例: type SubType<Type, SuperType> = [Type] extends [SuperType] ? Type : never

never

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.