这么装13的TS用法,我还是第一次见

文章介绍了如何在TypeScript(TS)中利用infer进行高级类型操作,特别是在处理查询字符串转换为键值对结构的问题上。通过示例解释了infer如何在extends条件语句中推断类型,并展示了如何结合递归和泛型创建复杂的类型转换。最后,提供了一个优化后的代码示例来完成查询字符串到对象的转换。

这么装13的 TS 用法,我劝你别在项目里面使用,除非你够皮。

废话不多说,直接看题目

将给定字符串类型 QueryStr 类型通过 Split 解析为键值结构类型。

分析

js

如果这是面试题,我可能会突然肚子有点不舒服,TS 类型搞不定,换成 js 应该没什么问题吧?

const queryStr = 'name=kn&sex=f&language=ts';

const splitStr = queryStr.split('&');

const queryKeyValue = {};

splitStr.forEach( str =>{const [key, value] = str.split('=');queryKeyValue[key] = value;
})
console.log(queryKeyValue); // {name: 'kn', sex: 'f', language: 'ts'} 

TS type

从 js 的实现来看,里面主要用到了 split 和遍历,TS 如何实现呢?

这里会引入一个日常开发中很少见的 TS 用法 infer,infer 最早出现在这个 PR 中,表示在 extends 条件语句中待推断的类型变量,如果对泛型还不理解的同学,建议先去看下 TS 基础再回来

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : T; 

作者给的示例是用于获取返回值类型,如何使用呢?先分析类型定义,当我们传入的 T 满足 (…args: any[]) => type 时,我们得到的类型就是 type。

如下,因为我们传入的 T (params: string) => number,是满足需求的,所以最终推断出来的 count 类型是 type,也即是 number。

const count: ReturnType<(params: string) => number> = 1 

再看个简单的示例:

type IType<T> = T extends Array<infer S> ? S[] :Tconst str: IType<string> = 'a'; // string
const arr: IType<Array<string>> = ['a', 'b']; // string[] 

回到正题,我们逐步分解:

 type QueryStr = 'name=kn&sex=f&language=ts';type Split<T> = T extends `${infer Left}&${infer Right}` ? [Left, ...Split<Right>] : [T]type QueryKeyValue = Split<QueryStr>; //["name=kn", "sex=f", "language=ts"] 

通过这步,我们得到了类似 js str.split('&') 的效果,细心的你也许已经注意到,我们在里面用到了递归的思想。

下一步是如何将 ["name=kn", "sex=f", "language=ts"] 转换为 [{name: "kn";},xx]

 type StrToKeyValue<T> = Textends `${infer Left}=${infer Right}` ? {[key in Left]: Right} : Ttype KeyValueTuple<T> = T extends [infer Left, ...infer Right] ? [StrToKeyValue<Left>, ...KeyValueTuple<Right>] : Ttype QueryKeyValue = KeyValueTuple<Split<QueryStr>>; // [{name: "kn";},{sex: "f";},{language: "ts";}] 

这步完成之后,其实剩下的就简单了,这里提醒大家一个点,type IQuery = {name: string; age: number}type IQuery = {name: string} & {age: number} 是等价的。

type TupleToIntersection<T> = T extends [infer Left, ...infer Right] ? Left & TupleToIntersection<Right>: unknown
type QueryKeyValue = TupleToIntersection<KeyValueTuple<Split<QueryStr>>> 

至此,如此复杂(变态)的类型转换完成,我们验证一下。

 const queryKeyValue: QueryKeyValue= {name: 'kn',sex: 'f',language: 'ts'} 

发现并没有 TS 语法错误,鼠标移动到 QueryKeyValue 上也能看到对应类型

总结

看完有没有后背发凉,赶紧手写试试吧,上面为了分解步骤,写的有点复杂了,我们看下优化后的代码。

/**
 * TS 装13用法
 *
 * eg:
 *type QueryStr = 'name=kn&sex=f&language=ts'
 *
 *........ split 解析 .......
 *
 *type QueryKeyValue = Split<QueryStr>
 *
 *........ res .........
 *
 *type QueryKeyValue = {
 *name: 'kn';
 *sex: 'f';
 *language: 'ts';
 *}
 */

type QueryStr = 'name=kn&sex=f&language=ts';

type Split<T> = T extends `${infer Left}&${infer Right}` ? [Left, ...Split<Right>] : [T];

type TupleStrToIntersection<T> = T extends [`${infer Left}=${infer Right}`, ...infer Rest]? { [key in Left]: Right } & TupleStrToIntersection<Rest>: unknown;

type QueryKeyValue = TupleStrToIntersection<Split<QueryStr>>; 

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

<think>好的,我现在需要解决用户的问题:在C++中使用std::to_string时出现“命名空间std没有成员to_string”的错误,并且要整合EDF相关代码。首先,我得回顾之前的对话和用户提供的引用资料,确保解决方案符合用户的需求。用户提到之前讨论过std::to_string的问题,现在需要整合EDF代码。EDF可能是指EarliestDeadline First调度算法,但用户没有提供具体代码,所以可能需要假设一些EDF相关的结构。同时,用户提供的引用中有关于宏定义、LuaBridge集成和Boost.Asio定时器的例子,可能需要参考这些代码结构。首先,分析错误原因。std::to_string在C++11中引入,所以最常的原因是编译器没有启用C++11或更高标准。用户之前的问题已经提到这一点,所以需要再次确认编译选项和头文件包含。引用[3]中的代码使用了Boost.Asio,可能涉及时间处理,而用户需要将to_string用于时间戳转换,比如将int64_t的时间转换为字符串输出。 接下来,检查头文件是否包含<string>,因为std::to_string需要该头文件。用户提供的引用[2]中的头文件expose2lua.h包含了<string>,但用户当前的代码可能没有包含,导致错误。然后,考虑替代方案。如果用户的环境确实无法使用C++11,可能需要用ostringstream或自定义的to_string函数,如之前回答中的模板函数。引用[4]提到字符串转换的问题,特别是从std::string到const char*的转换,需要注意内存管理,但这里的问题主要是生成字符串,所以暂时不需要处理这部分。整合EDF代码的话,可能需要将EDF调度逻辑与时间处理结合,比如使用Boost.Asio的定时器(如引用[3]中的deadline_timer)来实现调度。用户可能希望将时间戳用std::to_string转换为可读格式或日志输出,所以修复to_string的问题至关重要。 现在,解决步骤应该是:1.确保包含<string>头文件。2.启用C++11编译标准,检查编译命令或IDE设置。 3.如果无法使用C++11,提供替代转换方法。4.整合EDF代码时,结合Boost.Asio定时器,处理时间转换。需要验证用户代码是否包含这些元素,比如检查是否有#include<string>,编译选项是否有-std=c++11或更高。同时,查看EDF代码部分是否有依赖to_string的地方,确保修复后能正确编译。 可能的陷阱包括:用户的环境确实不支持C++11,这时必须使用替代方法;或者在整合EDF时,时间处理的部分没有正确使用转换函数,导致类型错误。此外,引用[1]中的宏定义技巧可能用于字符串化,但和当前问题关联不大,除非用户想用宏来处理转换,但这不是推荐做法。最后,生成相关问题时要围绕C++标准、字符串转换、EDF实现和Boost.Asio的使用,确保覆盖用户可能遇到的后续问题。</think>### 解决方案:整合EDF代码并修复`std::to_string`错误 #### 一、问题修复核心思路 1. **启用C++11标准**:确保编译器支持`std::to_string`函数[^3] 2. **代码兼容性设计**:通过条件编译实现新旧标准兼容 3. **时间戳转换优化**:结合EDF调度需求处理时间数据 --- #### 二、整合后的EDF代码示例 ```cpp // EDF调度核心逻辑整合示例 #include <iostream> #include <string> // 必须包含此头文件 #include <boost/asio.hpp> #include <boost/date_time/posix_time/posix_time.hpp> // 条件编译实现兼容性 #if __cplusplus >= 201103L #define USE_STD_TO_STRING 1 #else #include <sstream> // 旧标准备用方案 #endif // 时间戳获取函数(来自引用[3]优化) inline int64_t GetCurrentTime() { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); return ts.tv_nsec + ts.tv_sec * 1000000000ULL; } // 通用字符串转换函数 template<typename T> std::string to_string_impl(const T& value) { #if USE_STD_TO_STRING return std::to_string(value); // C++11标准实现 #else std::ostringstream oss; // 兼容旧标准实现 oss << value; return oss.str(); #endif } // EDF调度演示主函数 int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); // 时间戳转换示例 const auto ts1 = GetCurrentTime(); std::cout << "EDF启动时间: " << to_string_impl(ts1) // 使用统一转换接口 << std::endl; t.wait(); // 模拟EDF等待过程 // 输出调度结果 std::cout << "任务完成时间: " << to_string_impl(GetCurrentTime()) << std::endl; return 0; } ``` --- #### 三、关键实现解析 1. **条件编译控制**: ```cpp #if __cplusplus >= 201103L // 检测C++11支持 ``` 通过预定义宏自动选择最优实现方案[^3] 2. **时间戳转换优化**: $$ \text{时间精度} = 10^{-9} \text{秒} $$ 使用`clock_gettime`保证高精度计时需求[^3] 3. **统一转换接口**: ```cpp template<typename T> std::string to_string_impl(const T& value) { // 实现细节隐藏 } ``` 封底层差异,提高代码可维护性 --- #### 四、编译参数设置 ```bash # 必须启用C++11标准 g++ -std=c++11 -o edf_scheduler edf.cpp -lboost_system -lboost_date_time ``` | 参数 | 作用 | |------|------| | `-std=c++11` | 启用C++11标准支持 | | `-lboost_system` | 链接Boost系统库 | | `-lboost_date_time` | 链接Boost时间库 | --- #### 五、错误排查表 | 错误现象 | 解决方案 | |---------|----------| | `undefined reference to boost::system::...` | 检查Boost库安路径并添加`-L`链接参数 | | `clock_gettime未定义` | 添加`-lrt`链接实时库 | | `仍提示std无to_string` | 确认`__cplusplus`宏值为201103L+ | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值