Symbol.toPrimitive 的相关含义

解释一下这个语法: [Symbol.toPrimitive](hint: 'string' | 'number' | 'default'): string;

[Symbol.toPrimitive](hint: 'string' | 'number' | 'default'): string; 的含义:

1. Symbol.toPrimitive 是什么

Symbol.toPrimitive 是 JavaScript 的内置 Symbol,用于自定义对象转换为原始值(string、number 或 boolean)的行为。

2. 方括号 [] 的用法(计算属性名)

在对象字面量或类/接口中,[Symbol.toPrimitive] 表示使用 Symbol 作为属性名(计算属性名),而不是字符串 'Symbol.toPrimitive'

// 等价于
interface Example {
  [Symbol.toPrimitive]: Function;  // 属性名是 Symbol 本身
}

// 不同于
interface Example {
  'Symbol.toPrimitive': Function;  // 属性名是字符串
}

3. hint 参数的含义

hint 指示转换目标类型:

  • 'string':期望字符串
  `${obj}`  // hint = 'string'
  String(obj)  // hint = 'string'
  obj + ''  // hint = 'string'
  • 'number':期望数字
  +obj  // hint = 'number'
  Number(obj)  // hint = 'number'
  obj * 1  // hint = 'number'
  obj > 0  // hint = 'number'
  • 'default':不明确或默认
  obj == other  // hint = 'default'
  obj + 1  // hint = 'default'(如果 obj 不是数字,可能期望字符串)

4. 在代码中的应用

const result = {
  path: '/api/users/123',
  queryParams: new URLSearchParams('page=1'),

  [Symbol.toPrimitive](hint: 'string' | 'number' | 'default'): string {
    // 根据 hint 决定返回什么
    if (hint === 'string' || hint === 'default') {
      // 构建完整 URL
      return `${this.path}?${this.queryParams.toString()}`;
    }
    // hint === 'number' 时(通常不适用于 URL)
    return 0;
  }
};

// 使用示例:
console.log(`${result}`);        // '/api/users/123?page=1' (hint = 'string')
console.log(String(result));     // '/api/users/123?page=1' (hint = 'string')
console.log(result + '');        // '/api/users/123?page=1' (hint = 'string')
console.log(result == '/api/users/123?page=1');  // true (hint = 'default')

5. 在你的用例中

export interface UrlLiteralResult {
  [Symbol.toPrimitive](hint: 'string' | 'number' | 'default'): string;
}

作用:
- 当对象在字符串上下文中使用(如模板字符串、字符串拼接、String())时,自动调用并返回完整 URL
- hint'string''default' 时,返回完整 URL 字符串
- 通常忽略 'number',但为保持签名一致也可返回字符串(或 NaN

效果:

const url = urlLiteral`/api/users/:id`.params({ id: 123 }).query({ page: 1 });

// 所有这些都会自动调用 [Symbol.toPrimitive]('string')
const str1 = `${url}`;           // '/api/users/123?page=1'
const str2 = 'GET ' + url;       // 'GET /api/users/123?page=1'
const str3 = String(url);        // '/api/users/123?page=1'
fetch(url);                      // 也会自动转换为字符串

总结

这个语法定义了:
1. 属性名:Symbol.toPrimitive(Symbol 本身,不是字符串)
2. 参数:hint 表示期望的转换类型
3. 返回值:通常是字符串
4. 行为:对象在需要原始值时,自动调用该方法进行转换

这样就不需要手动调用 toString(),对象会在需要字符串时自动转换。