1
nomagick 275 天前 1
```typescript
interface wtf { id: string; [k: string]: number; } ``` |
2
liahu 275 天前
{
id: string [key: string]: any } ??? |
3
simoger 275 天前
interface MyObject {
id: string; [key: string]: number | string; } 这种? |
4
lilei2023 275 天前
这不是有三位热心网友帮你实现了一个么?
|
5
retrocode 275 天前
这种?
```ts interface Obj { id: string } interface Somebody extends Obj { key?: number } ``` |
6
wednesdayco OP @lilei2023 上面三位都不对
|
7
retrocode 275 天前
明白你意思了, 我理解问题, 1 楼是对的
|
8
retrocode 275 天前
你不妨 给个具体示例, 看你回复上面都不对完全不理解什么意思了
|
9
wednesdayco OP @retrocode 1 楼也不对
Property 'id' of type 'string' is not assignable to 'string' index type 'number'.ts(2411) |
10
wednesdayco OP @liahu 其他的属性值的类型必须是 number ,除了属性 id 的值的类型必须是 string
|
11
wednesdayco OP @simoger 除属性 id 的值的类型是 string 之外,其他的值的类型都必须是 number
|
12
MRG0 275 天前
放一个数据样例更好解决问题
|
13
tearzx 275 天前
interface A{
[key: string]: number; } interface B { id: string; } type C = A | B; |
14
nomagick 275 天前
还真是,等一个答案
|
15
wednesdayco OP @tearzx 不能限制 id 的类型,这样 id 可以为 number
|
16
wednesdayco OP @MRG0
const data: IData = { id: 'xxx-xxx-xxx', // id 只能是 string cid: 123123123, name: 233233, ...//任意属性,但值必须是 number 不能是其他的或者 string } |
17
Pencillll 275 天前 via Android
实现不了,因为没有办法把 'id' 从 string 里面排除出来
|
18
fannheyward 275 天前
#3 是对的
``` interface IData { id: string [k: string]: number | string } ``` |
19
fannheyward 275 天前 1
@fannheyward 不对,这样其他 key 可以是 string 了
|
20
rrfeng 275 天前
string indexer MUST accommodate all members
|
21
nomagick 275 天前 1
我解开了
interface NumO { [k: string]: number; } type WithID<T> = { id: string; } & T; type WTF = WithID<NumO>; const v = { id: 'wtf' } as WTF; // OK v.id = 'str'; v.a = 3; v.b = 4; // Not OK v.c = 'sr'; |
22
gam2046 275 天前 1
interface A {
id: string; } interface B { [k: string]: number } type AB = A & B function sample(arg: AB) { arg.id = 'aaa' arg.bcd = 1234 } |
23
wednesdayco OP @nomagick 这样做在类型提示上确实是对的,问题在初始化的时候不能加除了 id 以外的属性
|
24
nomagick 275 天前
再加一个类型参数,现场合并。。。
真拧巴。。。 |
26
NoManPlay 275 天前 1
```
type CustomType = { [key: string]: number | string; } & { id: string; }; // 通过映射类型和条件类型来移除 id 属性外的 string 类型 type StrictCustomType = { [K in keyof CustomType]: CustomType[K] extends string ? (K extends 'id' ? string : never) : number; }; ``` |
27
wednesdayco OP @NoManPlay 想法很好,但是实际初始化 StrictCustomType 的对象的时候,会报错。
|
28
Pencillll 275 天前
对于初始化来说,如果可以加个 helper 函数的话,倒是有一种办法:
type CoercedItem<T> = { [K in keyof T]: K extends 'id' ? string : number } type ValidItem<T> = T extends CoercedItem<T> ? 'id' extends keyof T ? T : never : never function makeItem<T>(item: ValidItem<T>): T { return item } const a = makeItem({ id: 'x', no: 1 }) a.id = 'y' a.no = 2 const b = makeItem({ id: 'z' }) // 报错 const c = makeItem({ id: 1, no: 1 }) // 报错 const d = makeItem({ no: 1 }) |
29
Pencillll 275 天前
不过上面这样有个缺陷是初始化之后的对象不能再添加新的属性
|
30
CLMan 275 天前
好奇什么场景需要这么复杂的类型定义呢?
或者说类似问题的类型约束的严谨性和代码简洁应该如何取舍? 我个人是把 TS 当作一个不太完美的类型约束工具,更倾向于代码简洁性。 |
31
Gaoti 273 天前
```ts
type Others = Record<string, number>; type T<O = Others> = { id: string; } & { [K in keyof O]: K extends "id" ? string : number; }; const obj: T<{ id: string; aaa: number }> = { id: "1", aaa: 123, bbb: 1, // error }; ``` 使用的时候泛型传入对应的类型就行,但是和 #28 说的一样,泛型中没有定义的的字段会报错 |
32
chnwillliu 233 天前 via Android
const id = ()=> ('i' + 'd ').trim();
const n:number = obj[id()]; 如果有这样的类型你这样操作那 TS 该不该报错? key 是运行时决定,所以有可能是 string 也有可能是 number 。 |