Typescript FAQ
约 4 分钟阅读
标签:FAQ
- 部分类型参数推导 #26242GitHub Issuemicrosoft/TypeScript#26242
- monorepo 类型问题 TypeScript#25376GitHub Issuemicrosoft/TypeScript#25376
- 目前就 npm monorepo 工作相对正常
- interface 定义 static
abstract staticTypeScript#34516GitHub Issuemicrosoft/TypeScript#34516- specifying interface implements clauses #33892GitHub Issuemicrosoft/TypeScript#33892
- typescript 没有 ESM
- 直接 import 会有问题, 多一层 default
- Provide TypeScript as an ESM #32949GitHub Issuemicrosoft/TypeScript#32949
- Use ESM for our executables #51440GitHub Issuemicrosoft/TypeScript#51440
# type checking
pnpm add -Dw @typescript/native-preview
# 无法排除 node_modules 问题 https://github.com/microsoft/TypeScript/issues/40426
npx tsc -p tsconfig.json --skipLibCheck --maxNodeModuleJsDepth 0 --noEmit
# 减少 node_modules 输出
npx tsc -p tsconfig.json --skipLibCheck --maxNodeModuleJsDepth 0 --noEmit | grep -v '/node_modules'null
用
undefined. 不要用null.-- Coding Guidelines for Contributors to TypeScript.
- undefined
- 无值,不能被序列化
- not been assigned a value
- null
- 有值,值为 null,能序列化
- 可以保持 object 的 key 存在
- intentional absence
- resource not ready
foo == null- 会匹配
null和undefined
- 会匹配
- 参考
tsconfig.tsbuildinfo
--incremental
type vs interface
建议优先 interface
- 更直观 - 写法和功能上
- 对熟悉其他语言的人来说更好理解
- 弱于
type- 避免太复杂
type- Type alias
- 可以表示任意类型
- 支持 union、mapped type、conditional type、tuple
- 隐含
Record<PropertyKey, unknown> - type 定义后就不可变了
interface- 可以 extends - 会比 type
&快一点 - 同名会做合并
- 通常是不希望的结果
- 可以作为扩展点,库提供定义类型的能力
- 可以 extends - 会比 type
- www.typescriptlang.org/docs/handbook/2/everyday-types.html
- 建议优先 interface
- www.totaltypescript.com/type-vs-interface-which-should-you-use
- Stop Using TypeScript Interfaces
enum vs union
- enum
- 有类型,不能直接赋值
- union
// 可以遍历的 ENUM
const permissions = ['read', 'write', 'execute'] as const;
type Permission = (typeof permissions)[number];
// 使用 ENUM 且可以遍历的方式
enum Permission {
Read = 'r',
Write = 'w',
Execute = 'x',
}
const Permission = {
Read: 'r',
Write: 'w',
Execute: 'x',
} as const;
type Permission = (typeof Permission)[keyof typeof Permission];- jsonschema 也有这个问题
- enum 是数组,不能有 title
- oneOf/anyOf 可以有 title - union
- stackoverflow.com/a/60041791/1870054
为每个方法添加一个参数
Expected 3 type arguments, but got 1
- TS 5.0 不支持部分参数推导
- stackoverflow.com/a/55754981/1870054
- #10571GitHub IssueMicrosoft/TypeScript#10571 Allow skipping some generics when calling a function with multiple generics
- #26242GitHub IssueMicrosoft/TypeScript#26242 Partial Type Argument Inference
箭头函数使用泛型参数
arrow function use generic type parameter
const identity = <T>(value: T): T[] => {
return [value];
};// TSX
const identity = <T,>(arg: T): T => arg;Path alias
- 推荐
@/*->src/*- 简单好配置
- 适用于大多场景
- 尽量保持使用相同的 alias 位置,让代码夸项目粘贴复制方便
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
alias: {
'@/': new URL('./src/', import.meta.url).pathname,
},
},
});{
"jsc": {
"baseUrl": "./",
"paths": {
"@/*": ["@/*"]
}
}
}- module-aliasnpm 包module-aliasNPM
- self link
- PNPM
- pnpm.io/aliases
- pnpm/pnpm#6316GitHub Issuepnpm/pnpm#6316
- dependencies
"src": "workspace:web@^"
- yarnpkg.com/configuration/yarnrc
- PNPM
- nextjs
ts-node
- esm 有问题 TypeStrong/ts-node/discussions/1450#discussion-3563207GitHubTypeStrong/ts-node/discussions/1450#discussion-3563207
npm add -D tsconfig-paths依赖包tsconfig-pathsnpm 包tsconfig-pathsNPM
{
"ts-node": {
"require": ["tsconfig-paths/register"]
}
}- TypeStrong/ts-nodeGitHubTypeStrong/ts-node推荐使用 tsx · ts-node 不支持 watch,默认参数可用性低 · TypeStrong/ts-node · node 直接执行 ts · watch · nodemon · ts-node-dev · tsconfig.json#ts-node笔记:ts-node
I 接口命名前缀
- 觉得需要用的时候就用
- 类和接口同时存在
- 如果只有接口没有实现时,不要加前缀
// user.ts
// IUserService 仅提供给使用方
export class UserService implements IUserService {}
export interface IUserService {}
// index.ts
// 对外只暴露接口,避免 import 的时候导入源码增加 bundle
export { type IUserService } from 'user.ts';
// client.ts
import type { IUserService } from 'server';
// 客户端不需要 bundle 源码
const svc = getService<IUserService>('user');DEV
declare var __DEV__: boolean;使用 pnpm 安装,Typescript 报类型错误
- 尝试 preserveSymlinks
{
"compilerOptions": {
"preserveSymlinks": true
}
}Types of property 'propTypes' are incompatible
method-signature-style
interface Example {
// method shorthand syntax
func(arg: string): number;
// regular property with function type
func: (arg: string) => number;
}- method args - bivariant
- function args - contravariant
- microsoft/TypeScript#18654GitHub PRmicrosoft/TypeScript#18654
as const
- const assertions
- 不会让类型变宽 -
'hello'不会变为string - 都是 readyonly
- www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html
bundle/rollup d.ts
- rollup-plugin-dtsGitHubSwatinem/rollup-plugin-dts
- 不支持 path
- rollup-plugin-tsGitHubwessberg/rollup-plugin-ts
- timocov/dts-bundle-generatorGitHubtimocov/dts-bundle-generator
- Microsoft/TypeScript#4433GitHub IssueMicrosoft/TypeScript#4433
- bun bundle 逻辑
The inferred type of '' cannot be named without a reference to sequelize
TypeScript#42873GitHub Issuemicrosoft/TypeScript#42873
# tsconfig 可以调整为 include 需要的内容
pnpm tsc -p ./tsconfig.json --noEmit false --emitDeclarationOnly true --declaration true --outDir ./dist/types
# 直接生成
pnpm tsc --target ESNext --jsx preserve --declaration --strict --pretty --out ./dist/server.js --module system --moduleResolution node --emitDeclarationOnly ./src/server/routers/_app.tsModule 'wechat4u' resolves to an untyped module at , which cannot be augmented.
将所有的类型定义都放在 declare module 里
TS6133: 'React' is declared but its value is never read.
- jsx: react
- microsoft/TypeScript#41882GitHub Issuemicrosoft/TypeScript#41882
SyntaxError: This experimental syntax requires enabling one of the following parser plugin(s): "decorators", "decorators-legacy".
export default {
importOrderParserPlugins: ['typescript', 'decorators-legacy'],
};mixin
Polymorphic React Props
import * as React from "react";
type BoxProps<E extends ElementType> = Omit<ComponentProps<E>, 'as'> & {
as?: E;
};
const Box = <E extends ElementType = 'div'>({ as, ...props }: BoxProps<E>) => {
const TagName = as || 'div';
return <TagName {...props} />;
};
type PolymorphicProps<P extends { as?: T }, T extends React.ElementType> = P &
Omit<React.ComponentPropsWithoutRef<T>, keyof P>;
type ButtonProps<T extends React.ElementType> = PolymorphicProps<
{
as?: T;
icon?: React.ReactNode;
children?: React.ReactNode;
},
T
>;
function Button<T extends React.ElementType = "button">({
as,
...props
}: ButtonProps<T>
) {
const Component = as || "button";
return <Component {...props} />;
}NullableOptional
type RequiredKeys<T> = {
[K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K;
}[keyof T];
type OptionalKeys<T> = {
[K in keyof T]-?: {} extends { [P in K]: T[K] } ? K : never;
}[keyof T];
type PickRequired<T> = Pick<T, RequiredKeys<T>>;
type PickOptional<T> = Pick<T, OptionalKeys<T>>;
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
type NullableOptional<T> = PickRequired<T> & Nullable<PickOptional<T>>;SyntaxError: A type-only import can specify a default import or named bindings, but not both
import type React, { type ReactNode } from 'react';TS2742
- 当使 declaration 时会要求
- 当 composite 时, 强制要求 declaration
- 用于配合 references 使用
TS2742: The inferred type of X cannot be named without a reference to Y. This is likely not portable. A type annotation is necessary.
关联信息
反向链接、本文链接的其他页面和外部资料。
反向链接
- trpc笔记 · bundle/rollup d.ts · bundlerollup dts
trpc/trpc · @trpc/next - NextJS · spec · https://trpc.io/docs/rpc · 参考 · jlalmes/trpc-openapi · 使用 meta 定义路由 · - · 使用 zod 定义 input 和 output
参考资料
GitHub24 条
- Microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefinedgithub.com/Microsoft/TypeScript/wiki/Coding-guidelines
- Microsoft/TypeScript#10571github.com/Microsoft/TypeScript/issues/10571
- microsoft/TypeScript#18654github.com/microsoft/TypeScript/pull/18654
- microsoft/TypeScript#25376github.com/microsoft/TypeScript/issues/25376
- microsoft/TypeScript#26242github.com/microsoft/TypeScript/issues/26242
- Microsoft/TypeScript#26242github.com/Microsoft/TypeScript/issues/26242
- microsoft/TypeScript#29808github.com/microsoft/TypeScript/issues/29808
- microsoft/TypeScript#32949github.com/microsoft/TypeScript/issues/32949
- microsoft/TypeScript#33892github.com/microsoft/TypeScript/issues/33892
- microsoft/TypeScript#34516github.com/microsoft/TypeScript/issues/34516
- microsoft/TypeScript#41882github.com/microsoft/TypeScript/issues/41882
- microsoft/TypeScript#42873github.com/microsoft/TypeScript/issues/42873
- Microsoft/TypeScript#4433github.com/Microsoft/TypeScript/issues/4433
- microsoft/TypeScript#51440github.com/microsoft/TypeScript/issues/51440
- oven-sh/bun/packages/bun-types/scripts/bundle.tsgithub.com/oven-sh/bun/blob/main/packages/bun-types/scripts/bundle.ts
- pnpm/pnpm#6316github.com/pnpm/pnpm/issues/6316
- Swatinem/rollup-plugin-dtsgithub.com/Swatinem/rollup-plugin-dts
- timocov/dts-bundle-generatorgithub.com/timocov/dts-bundle-generator
- trivago/prettier-plugin-sort-imports#120github.com/trivago/prettier-plugin-sort-imports/issues/120
- TypeStrong/ts-nodegithub.com/TypeStrong/ts-node
- TypeStrong/ts-node/discussions/1450#discussion-3563207github.com/TypeStrong/ts-node/discussions/1450
- urql-graphql/urql#792github.com/urql-graphql/urql/issues/792
- vercel/turbo/discussions/620github.com/vercel/turbo/discussions/620
- wessberg/rollup-plugin-tsgithub.com/wessberg/rollup-plugin-ts
依赖包1 条
- module-aliaswww.npmjs.com/package/module-alias
其他外链14 条
- 2ality.com/2021/01/undefined-null-revisited.html2ality.com/2021/01/undefined-null-revisited.html
- dev.to/afzalimdad9/stop-using-typescript-interfaces-1lc2dev.to/afzalimdad9/stop-using-typescript-interfaces-1lc2
- pnpm.io/aliasespnpm.io/aliases
- stackoverflow.com/a/41967120/1870054stackoverflow.com/a/41967120/1870054
- stackoverflow.com/a/49479117/1870054stackoverflow.com/a/49479117/1870054
- stackoverflow.com/a/55754981/1870054stackoverflow.com/a/55754981/1870054
- stackoverflow.com/a/60041791/1870054stackoverflow.com/a/60041791/1870054
- www.totaltypescript.com/type-vs-interface-which-should-you-usewww.totaltypescript.com/type-vs-interface-which-should-you-use
- www.typescriptlang.org/docs/handbook/2/everyday-types.htmlwww.typescriptlang.org/docs/handbook/2/everyday-types.html
- www.typescriptlang.org/docs/handbook/mixins.htmlwww.typescriptlang.org/docs/handbook/mixins.html
- www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.htmlwww.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html
- www.typescriptlang.org/docs/handbook/triple-slash-directives.htmlwww.typescriptlang.org/docs/handbook/triple-slash-directives.html
- www.typescriptlang.org/playwww.typescriptlang.org/play
- yarnpkg.com/configuration/yarnrcyarnpkg.com/configuration/yarnrc