# @creditkarma/thrift-typescript 中文文档

规范地址：https://npmcn.com/package/%40creditkarma/thrift-typescript/

版本：3\.7\.6
npm 元数据更新时间：2022-06-12T16:46:00.051Z
中文译文更新时间：2026-11-11T00:13:51.822Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40creditkarma/thrift-typescript
原文对照：https://npmcn.com/package/%40creditkarma/thrift-typescript/?lang=original
项目主页：https://github.com/creditkarma/thrift-typescript#readme
源码仓库：https://github.com/creditkarma/thrift-typescript

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：739 kB，271 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：5 个
- 首次发布：2017-09-27T20:08:20.806Z
- 最新版本发布：2019-09-03T19:21:45.856Z
- 近 30 天下载量：26666（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：125（近 12 个月 0 个）

## 中文简介

从 Thrift IDL 文件生成类型脚本

## 安装

```sh
npm install @creditkarma/thrift-typescript
```

也可以使用：`pnpm add @creditkarma/thrift-typescript`、`yarn add @creditkarma/thrift-typescript`、`bun add @creditkarma/thrift-typescript`

## README

# 线索类型

从 Thrift IDL 文件生成类型脚本 .

## 安装

```sh
$ npm install --save @creditkarma/thrift-typescript
```

## 使用量

Thrift TypeScript同时提供JavaScript和命令行API.

鉴于以下文件

节俭/简单.thrift

```c
struct MyStruct {
    1: required i32 id,
    2: required bool field1,
    # 3: required string field,
    4: required i16 field,
}
```

您可以通过命令行生成 TypeScript :

```sh
$ thrift-typescript --target apache --rootDir . --sourceDir thrift --outDir codegen simple.thrift
```

现有备选办法如下:

-   \--rootDir:用于解析出和源目录. 默认为当前目录 .
-   \--outDir: 要保存已生成文件的目录 。 如果它不存在,就会被创造出来 默认为“ codegen ” .
-   \--sourceDir:搜索源文件的目录. 默认为“ 撕裂 ” .
-   \--goal: 生成用于“ apache” 或“ thrift- server” 的核心库 。 默认为“ apache ” .
-   \--critical Unions:如果我们产生严格的结合(仅可用于目标='thrift-server'). 更多关于这一点,见下文)。 未定义的默认值 .
-   \-- fallbackNamespace: 如果不存在'j's' namespace, 则返回的名称空间 。 默认为"java". 设定为“ 无” 无法使用命名空间 .
-   \-- 使用Name 字段: 如果我们生成一个 `__name` 字段。 未定义的默认值 .

所有其他字段均被假定为源文件.

如果未提供文件的明确列表, 将会使用源代码“ . thrift” 中找到的所有文件 .

您可以从一个以上 Thrift 文件 中获取 gen 代码 :

```sh
$ thrift-typescript one.thrift two.thrift three.thrift
```

#### Java 脚本 API

您也可以使用 JavaScript API 生成文件 :

```typescript
import { generate } from '@creditkarma/thrift-typescript'

// Generates TypeScript and saves to given outDir
generate({
    rootDir: '.',
    sourceDir: 'thirft',
    outDir: 'codegen',
    target: 'thrift-server',
    files: [
        'simple.thrift'
    ],
    fallbackNamespace: 'java',
})
```

#### 向字符串倾斜

您也可以从 Thrift 的字符串中生成 TypeScript 而不保存到文件 .

说明: 这种代码生成方法并不支持包括. Thrift 生成器必须能够解析所有没有文件结构描述无法解析的标识符.

```typescript
import { readFileSync } from 'fs'
import { make } from '@creditkarma/thrift-typescript'

const rawThrift: string = readFileSync('./thrift/simple.thrift', 'utf-8')
const generatedCode: string = make(rawThrift)
```

## 调色器服务器

_鼠标类型中的 v2.x 等同@ creditkarma/thrift- server v. 7.0 或更高_

虽然Thrift TypeScript可以用来生成编码可与 [Apache 脉冲库](https://github.com/apache/thrift/tree/master/lib/nodejs),建议与 [调色器服务器](https://github.com/creditkarma/thrift-server)。关于Apache用法的详情如下.

Thrift Server在Express或Hapi中增加了有插件或中间软件的 Thrift支持. 与Thrift Server一起使用代码源的另一个外观是将上下文添加到服务客户端和服务处理器中. 在Thrift服务方法中,可以使用上下文来做诸如认证或追踪等事情. 背景是所有服务处理器方法和所有服务客户端方法的可选最终参数.

为您选择的服务器安装 Thrift 服务器执行 。 例如,我们将使用快递的中间软件和请求 http客户端库.

```sh
$ npm install --save @creditkarma/thrift-server-core
$ npm install --save @creditkarma/thrift-server-express
$ npm install --save @creditkarma/thrift-client
$ npm install --save express
$ npm install --save request
$ npm install --save @types/express
$ npm install --save @types/request
```

鉴于这项服务,让我们根据我们生成的代码建立一个客户端和服务器.

```c
service Caluculator {
    i32 add(1: i32 left, 2: i32 right)
    i32 subtract(1: i32 left, 2: i32 right)
}
```

运行代码源为您的脉冲服务。 这个 `target` 选项,否则生成的代码将只与 Apache libs 工作.

```sh
$ thrift-typescript --target thrift-server --rootDir . --sourceDir thrift --outDir codegen
```

### 客户端

在这个例子中,我们正在使用请求库作为我们的基本连接实例。 请求的选项(核心选项)是我们请求的背景.

你会发现客户类是普通的 类型参数代表上下文的类型. 这通常是类型 `CoreOptions` 从请求库.

```typescript
import {
    createHttpClient,
    HttpConnection,
} from '@creditkarma/thrift-client'

import * as request from 'request'
import { CoreOptions } from 'request'

import { Calculator } from './codegen/calculator'

const CONFIG = {
    hostName: 'localhost',
    port: 8045
}

const thriftClient: Calculator.Client<CoreOptions> = createHttpClient(Calculator.Client, CONFIG)

thriftClient.add(5, 7, { headers: { 'X-Trace-Id': 'xxxxxx' } })
    .then((response: number) => {
        expect(response).to.equal(12)
        done()
    })
```

### 服务器

在服务器上,我们可以检查 我们设置在客户端的头部.

```typescript
import * as bodyParser from 'body-parser'
import * as express from 'express'
import { ThriftServerExpress } from '@creditkarma/thrift-server-express'

import {
    Calculator,
} from './codegen/calculator'

// express.Request is the context for each of the service handlers
const serviceHandlers: Calculator.IHandler<express.Request> = {
    add(left: number, right: number, context?: express.Request): number {
        if (context && context.headers['x-trace-id']) {
            // You can trace this request, perform auth, or use additional middleware to handle that.
        }
        return left + right
    },
    subtract(left: number, right: number, context?: express.Request): number {
        return left - right;
    },
}

const PORT = 8090

const app = express()

app.use(
    '/thrift',
    bodyParser.raw(),
    ThriftServerExpress(Calculator.Processor, serviceHandlers),
)

app.listen(PORT, () => {
    console.log(`Express server listening on port: ${PORT}`)
})

```

### 生成的数据类型

在从 Thrift 源生成 TypeScript 数据类型时 ?

#### 简单类型

它们是:布林斯克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克 所有这些几乎都直接翻译为TypeScript.

给定方向 :

```c
const bool FALSE_CONST = false
const i32 INT_32 = 32
const i64 INT_64 = 64
const list<string> LIST_CONST = ['hello', 'world', 'foo', 'bar']
const set<string> SET_CONST = ['hello', 'world', 'foo', 'bar']
const map<string,string> MAP_CONST = { 'hello': 'world', 'foo': 'bar' }

enum Colors {
    RED,
    GREEN,
    BLUE,
}

typedef string name
```

生成类型脚本 :

```typescript
export const FALSE_CONST: boolean = false;
export const INT_32: number = 32;
export const INT_64: thrift.Int64 = new thrift.Int64(64);
export const LIST_CONST: Array<string> = ["hello", "world", "foo", "bar"];
export const SET_CONST: Set<string> = new Set(["hello", "world", "foo", "bar"]);
export const MAP_CONST: Map<string, string> = new Map([["hello", "world"], ["foo", "bar"]]);

export enum Colors {
    RED,
    GREEN,
    BLUE
}

export type name = string;
```

这里唯一有趣的是处理 `i64`。JavaScript不支持一个完整的64位整数精度,所以我们把数值用一个 `Int64` 对象。 你会注意到,这真的没有帮助 在你定义 常数或默认值 在你的Thrift文件中, 但是它确实允许 从JS以外的64位整数 得到正确处理。 该对象导出自 `@creditkarma/thrift-server-core` 扩展 [节点-int64](https://github.com/broofa/node-int64)。 。 。 .

#### 结构

结构在直观上类似于接口.

给定方向 :

```c
struct User {
    1: required string name
    2: string email
    3: required i32 id
}
```

生成类型脚本 :

```typescript
export interface IUser {
    name: string
    email?: string
    id: number
}
```

_注意:我们采用大写"I"的前缀界面名称的常规._

只有明确要求解开的字段 `?`。 。 。 .

##### 这个 `__name` 外地

您可以通过一个选项, 在每个类似结构( structs, 结合, 例外) 对象上生成一个额外的属性, 也就是其字面名称 Thrift 文件 .

例如,如果我们做了 `User` 与结构 `--withNameField` 选项:

```typescript
export interface IUser {
    __name: "User"
    name: string
    email?: string
    id: number
}
```

在使用此选项生成数据时, 您创建并传递到客户端方法中的任何数据类型都不需要 `__name` 字段。 然而,您从服务中获得的任何数据都会包含这个额外的属性.

#### 工会

斯里夫特的联盟与结构非常相近. 区别在于它们只允许设置一个字段. 它们还要求设置一个领域。 隐含所有字段都是可选的,但必须设置一个字段.

因此,这转化为一个有所有可选字段的结构:

给定方向 :

```c
union MyUnion {
    1: string option1
    2: i32 option2
}
```

生成类型脚本( 没有严格的结合) :

```typescript
export interface IMyUnion = {
    option1?: string
    option2?: undefined
}
```

_说明: 这里的区别是, 如果一个字段没有设置, 或者如果设置了多个字段, 则会出现运行时间错误 ._

#### 例外

例外是使用服务方法可以抛出的错误. 联合来文/技术服务更自然地造成并造成新的错误。 所以,我们确定的例外 将成为JS课程.

给定方向 :

```c
exception MyException {
    1: string message
    2: i32 code
}
```

生成类型脚本 :

```typescript
export class MyException extends thrift.StructLike implements IMyException {
    public message: string
    public code?: number
    constructor(args?: { message?: string, code?: number }) {
        // ...
    }
}
```

然后在你的服务客户端 你可以放弃例外 因为你会任何JS错误 `throw new MyException({ message: 'whoops', code: 500 });`

#### 服务

服务有点复杂。 服务有两个部分。 这是 `Client` 发送服务请求和 `Processor` 用于处理服务请求。 服务 `Client` 服务 `Processor` 每个生成的类。 它们和其他一些内部物体一起被包裹在 `namespace` 那有您服务的名字.

给定方向 :

```c
service MyService {
    User getUser(1: i32 id) throws (1: MyException exp);
}
```

生成类型脚本 :

```typescript
export namespace MyService {
    export class Client<Context> {
        constructor(connection: thrift.IThriftConnection<Context>) {
            // ...
        }
        getUser(id: number): Promise<User> {
            // ...
        }
    }
    export interface IHandler<Context> {
        getUser(id: number, context?: Context): User | Promise<User>
    }
    export class Processor {
        constructor(handler: IHandler<Context>) {
            // ...
        }
        public process(input: thrift.TProtocol, output: thrift.TProtocol, context: Context): Promise<Buffer> {
            // ...
        }
    }
}
```

这个 `Client` 相当直线前进。 你创造了一个 `Client` 实例,您可以调用服务方法。 内部工作 `Processor` 消费者不需要关心的东西。 最有趣的一点是 `IHandler`。这是服务小组为履行服务合同的承诺而需要实施的接口。 创建满足对象 `<service-name>.IHandler` 并传递给建造者 `<service-name>.Processor` 其他的都交给你了.

#### 闲置类型

鉴于这两个结构:

```c
struct User {
    1: required i64 id
}

struct Profile {
    1: required User user
    2: binary data
    3: i64 lastModified
}
```

在如何处理TypeScript中的事情和如何将数据传送到电线上,有些不同。 由于这个原因,当我们为这些结构生成接口时,我们为每个结构生成两个接口,一个是Thrift的精确表示,另一个是更松散的东西,为JavaScript中的数据工作提供了更大的灵活性.

主要的区别在于标记为 `i64` 可作为 `number`,作为 `string` 或一个 `Int64` 对象和 `binary` 可作为 `string` 或一个 `Buffer` 对象.

传统上的 JavaScript (`bigint` 是新且尚未完全支持)不支持64位整数。 这就是说我们需要包扎出刺刀 `i64` 类型 `Int64` 对象以保持精确度。 在您的 TypeScript 代码中, 您可能正在使用这些 `number` (自信的JavaScript的53位精度对于你足够好)或者作为一个 `string`。这些松散类型允许您这样做,生成的代码将处理转换到 `Int64` 给你的.

生成类型脚本 :

```typescript
interface IUser {
    id: thrift.Int64
}
interface IUserArgs {
    id: number | string | thrift.Int64
}
interface IProfile {
    user: IUser
    data?: Buffer
    lastModified?: thrift.Int64
}
interface IProfileArgs {
    user: IUserArgs
    data?: string | Buffer
    lastModified?: number | string | thrift.Int64
}
```

松散界面的名称只是附加 `Args` 在界面名称的末尾。 其原因是这些接口在您的代码中最常被用作参数.

松散的接口在哪里? 松散的界面可以用于任何您,应用程序开发者向生成的代码提供数据,或者作为客户端方法的参数,或者作为服务处理器的返回值.

如果我们有这个服务:

```c
service ProfileService {
    Profile getProfileForUser(1: User user)
    User getUser(1: i64 id)
}
```

生成类型脚本 :

```typescript
namespace ProfileService {
    export class Client<Context> {
        constructor(connection: thrift.IThriftConnection<Context>) {
            // ...
        }
        getProfileForUser(user: IUserArgs, context?: Context): Promise<IProfile> {
            // ...
        }
        getUser(id: number | string | Int64): Promise<IUser> {
            // ...
        }
    }
    export interface IHandler<Context> {
        getProfileForUser(user: IUser, context: Context): Promise<IProfileArgs>
        getUser(id: Int64, context: Context): Promise<IUserArgs>
    }
}
```

从这些生成类型的草图中可以看到,当数据离开应用程序代码并跨出边界进入生成的代码时,你可以传递松散的值,当数据来自生成的代码时,它总是属于严格的类型.

我们可以用一个 `User` 对象 `id` 是一个 `number` 或一个 `string` 不用包起来 `Int64`这些转换是为我们处理的。 A 类 `number` 传入的包裹 `Int64` 使用 `Int64` 构造器 : `new Int64(64)`A级 `string` 替换 `Int64` 使用静态转换 `fromDecimalString` 方法 : `Int64.fromDecimalString('64')`类似 `string` 数据可以传递到 `binary` 字段和转换为 `Buffer` 在引擎盖下处理。 这仅仅是说服接口,使TypeScript中的Thrift对象的处理更加容易. 您会注意到服务方法总是返回一个更严格的界面对象. 另外,更严格的接口总是可以通过预期松散接口的地方.

#### 发送数据 穿过电线

当涉及到结构类数据类型(struct, 联合和例外)时,通常你不需要比什么数据类型生成更多的了解. 然而,除了生成的接口/集成/分级外,代码生成器还创建了一个伴对象,知道如何将给定的对象发送到线上.

回想起来 `User` 来自我们结构示例的对象,除了接口外,代码生成器还创建了这样的编码对象:

```typescript
export const UserCodec: thrift.IStructCodec<IUserArgs, IUser> {
    encode(obj: IUserArgs, output: thrift.TProtocol): void {
        // ...
    },
    decode(input: thrift.TProtocol): IUser {
        // ...
    }
}
```

它仅仅是一个知道如何从 Thrift 协议读取给定对象或者将给定对象写入 Thrift 协议的对象.

解码器将永远遵循这个命名惯例,只是附加 `Codec` 位于您所命名的末尾.

### 严格结合

_注:要求严格结合 `thrift-server` 版本 `0.13.x` 或更高级._

仅当生成用于 `thrift-server`。此选项将生成TypeScript联盟。 这在几个重要方面改变了代码源.

回到我们的工会定义:

```c
union MyUnion {
    1: string option1
    2: i32 option2
}
```

与 `--strictUnions` 我们现在这样生成 TypeScript 旗:

```typescript
enum MyUnionType {
    MyUnionWithOption1 = "option1",
    MyUnionWithOption2 = "option2"
}
type MyUnion = IMyUnionWithOption1 | IMyUnionWithOption2
interface IMyUnionWithOption1 {
    __type: MyUnionType.MyUnionWithOption1
    option1: string
    option2?: undefined
}
interface IMyUnionWithOption2 {
    __type: MyUnionType.MyUnionWithOption2
    option1?: undefined
    option2: number
}
type MyUnionArgs = IMyUnionWithOption1Args | IMyUnionWithOption2Args
interface IMyUnionWithOption1Args {
    option1: string
    option2?: undefined
}
interface IMyUnionWithOption2Args {
    option1?: undefined
    option2: number
}
```

这个 `enum` 表示该表的所有潜在值 `__type` 与我们结合的每一个变体相关的财产。 而不是产生一个 `interface` 带有可选属性,我们为每个需要该字段的字段生成一个接口。 我们的结果 `type` 然后是多个接口的结合,每个接口只有一个属性。 这提供了编译时间的保证,即我们正在为工会确定一个和只有一个领域.

松散的接口 `Args` 界面,其行为与结构的松散接口相类似。 他们允许你使用 `number` 替换 `Int64` 或者让你通过 `string` 或者说 `Buffer` 页:1 `binary` 类型。 此外,他们也放弃了 `__type` 属性。 在代码中,我们可以分辨出 你经过你设置的田地。 这意味着在大多数情况下,你不需要提供 `__type` 属性。 您可以使用松散的接口作为服务函数的返回值或作为客户端方法的参数.

这个输出比较复杂,但它允许我们做一些事情. 其中最重要的可能是它使我们能够利用我们申请守则中的歧视结合:

```typescript
function processUnion(union: MyUnion) {
    switch (union.__type) {
        case MyUnionType.MyUnionWithOption1:
            // Do something
        case MyUnionType.MyUnionWithOption2:
            // Do something
        default:
            const _exhaustiveCheck: never = union
            throw new Error(`Non-exhaustive match for type: ${_exhaustiveCheck}`)
    }
}
```

我们生成的每个接口都定义了一个需要的字段和一些 n 选项 `undefined` 字段,我们可以做诸如检查 `union.option2 !== undefined` 没有编译器错误, 但是如果您尝试使用一个在给定的结合上不应该存在的值, 我们会得到编译器错误 。 这样可以扩大工会的运作方式,使之更加普遍.

使用此表单需要您向编译器证明您工会设置了一个字段( 并且只有一个) .

除更改类型输出外 `--strictUnions` 旗帜更改输出 `Codec` 对象。 这个 `Codec` 对象将有一个额外的方法 `create`编辑 `create` 方法取出一个松散的接口并强迫它进入严格的接口(包括: `__type` (b) 财产).

举个例子 `MyUnion` 定义为:

```typescript
const MyUnionCodec: thrift.IStructToolkit<IUserArgs, IUser> { = {
    create(args: MyUnionArgs): MyUnion {
        // ...
    },
    encode(obj: IUserArgs, output: thrift.TProtocol): void {
        // ...
    },
    decode(input: thrift.TProtocol): IUser {
        // ...
    }
}
```

_说明: 在未来的突破中 释放所有的 `Codec` 对象将重新命名为 `Toolkit` 因为它们将提供更多的公用设施,用于处理界定的闪烁物体._

## 阿帕奇脉冲

生成的代码也可以与 [Apache 脉冲库](https://github.com/apache/thrift/tree/master/lib/nodejs)。 。 。 .

```sh
$ npm install --save thrift
$ npm install --save @types/thrift
```

鉴于这项服务,让我们根据我们生成的代码建立一个客户端和服务器.

```c
service Calculator {
    i32 add(1: i32 left, 2: i32 right)
    i32 subtract(1: i32 left, 2: i32 right)
}
```

运行代码源为您的脉冲服务。 给 `--target` 选项不需要,因为 `apache` 是默认的构建目标.

```sh
$ thrift-typescript --rootDir . --sourceDir thrift --outDir codegen
```

### 客户端

```typescript
import {
    createHttpConnection,
    createHttpClient,
    HttpConnection,
} from 'thrift'

import { Calculator } from './codegen/calculator'

// The location of the server endpoint
const CONFIG = {
    hostName: 'localhost',
    port: 8045
}

const options = {
    transport: TBufferedTransport,
    protocol: TBinaryProtocol,
    https: false,
    headers: {
        Host: config.hostName,
    }
}

const connection: HttpConnection = createHttpConnection(CONFIG.hostName, CONFIG.port, options)
const thriftClient: Calculator.Client = createHttpClient(Calculator.Client, connection)

// All client methods return a Promise of the expected result.
thriftClient.add(5, 6).then((result: number) =>{
    console.log(`result: ${result}`)
})
```

### 服务器

```typescript
import {
    createWebServer,
    TBinaryProtocol,
    TBufferedTransport,
} from 'thrift'

import { Calculator } from './codegen/calculator'

// Handler: Implement the Calculator service
const myServiceHandler = {
    add(left: number, right: number): number {
        return left + right
    },
    subtract(left: number, right: number): number {
        return left - right
    },
}

// ServiceOptions: The I/O stack for the service
const myServiceOpts = {
    handler: myServiceHandler,
    processor: Calculator,
    protocol: TBinaryProtocol,
    transport: TBufferedTransport
}

// ServerOptions: Define server features
const serverOpt = {
    services: {
        '/': myServiceOpts
    }
}

// Create and start the web server
const port: number = 8045;
createWebServer(serverOpt).listen(port, () => {
    console.log(`Thrift server listening on port ${port}`)
})
```

## 页:1

宝石编码可以使用许多更严格的tsc编译器选项.

```json
{
    "compilerOptions": {
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "noUnusedLocals": true
    }
}
```

## 发展

安装依赖关系

```sh
npm install
```

### 构建

```sh
npm run build
```

### 在监视模式下运行测试

```sh
npm run test:watch
```

## 捐款

欲了解更多关于贡献新功能和错误修正的信息,请参见我们 [贡献准则](https://github.com/creditkarma/CONTRIBUTING.md)。 。 。 . 外部捐助者必须签署捐助者许可证协定

## 许可证

这个项目的许可证根据 [Apache 许可证版本 2.0](https://npmcn.com/package/%40creditkarma/thrift-typescript/LICENSE)

## 常见问题

### @creditkarma/thrift-typescript 是什么？

从 Thrift IDL 文件生成类型脚本

### 如何安装 @creditkarma/thrift-typescript？

在项目目录运行 npm install @creditkarma/thrift-typescript，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 thrift-typescript，可以用 npx thrift-typescript 直接运行。

### @creditkarma/thrift-typescript 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @creditkarma/thrift-typescript 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @creditkarma/thrift-typescript 可以商用吗？

@creditkarma/thrift-typescript 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @creditkarma/thrift-typescript 的下载量有多少？

根据 npm 官方下载统计，@creditkarma/thrift-typescript 在 2026/10/11 – 2026/11/09 这 30 天内被下载 26,666 次，日均约 889 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @creditkarma/thrift-typescript 还在维护吗？

最新版本 3\.7\.6 发布于 2019/09/04（7 年前）；至今共发布 125 个版本，其中过去 12 个月发布了 0 个；首次发布于 2017/09/28。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

