farrow-js / farrow

A Type-Friendly Web Framework for Node.js
https://www.farrowjs.com
MIT License
768 stars 37 forks source link

Question: 使用 type 定义的类型作为 json 参数时 ts 没问题,但是同样的定义用 interface 就报错了 #174

Closed zation closed 2 years ago

zation commented 2 years ago

很奇怪,不太清楚是不是 ts 的 bug

具体错误是:Argument of type 'UserInterface' is not assignable to parameter of type 'JsonType'. Type 'UserInterface' is not assignable to type '{ [key: string]: JsonType; }'. Index signature for type 'string' is missing in type 'UserInterface'.

复现的地址:https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgJQKYGdIDt2rgXzgDMoIQ4ByIgQylIHcBaACxhjAoG4AoUSWRHAASbMAWKlyVWgxaiu3bgGMIOeK3ZwAvMNEAKAJQ9uMAJ5g8AVVxQAKubw6E3OHGAATAFxwsAVxAARqhQ3PjGKmpwvjb2Ft7WwbGOiC5uXnCMAIwANKHGGmAAdADmqDB6FAD00YkOFAaFNXqG2gB8Ka5QZb5QWCgY2LiFAFboqno1dg5GoTO8WDDBNEpWNgCSC0vUKx1p3n6BwaGKEejwkxuLUMuo8eub19vJzq4e3lm5YYoFJWUV1fcrjd6o1cM0DG1dl0YD0+mhMKohqNxhcHjcZvgjEA

代码:

import { Response } from 'farrow-http';
import { Http } from 'farrow-http';

const http = Http();

type UserType = {
  id: number
};

const userType: UserType = {
  id: -1,
};

http.get('/userType').use(() => {
  return Response.json(userType); // ts compile ok
});

interface UserInterface {
  id: number
}

const userInterface: UserInterface = {
  id: -1,
};

http.get('/userInterface').use(() => {
  return Response.json(userInterface); // ts compile error
});
Lucifier129 commented 2 years ago

这个是 typescript 的限制,interface 可以多次声明、自动 merged,而 type 不是开放的,所以在 indexed type 的行为上有差异。

可以用下面这种方式转换:

export type ToType<T> = T extends object | unknown[]
  ? {
      [key in keyof T]: ToType<T[key]>
    }
  : T

interface UserInterface {
  id: number
}

type User = ToType<UserInterface>
zation commented 2 years ago

感谢回复

zation commented 2 years ago

话说,要不要考虑 Response.json 带个泛型默认用 any?不然每次都要转的话,用起来还是比较麻烦,虽然类型是更严谨的

Lucifier129 commented 2 years ago

框架可能不方便 any,框架使用者可以根据自己的需要 as any,这样也不用转。