 
 (use-package! typescript-mode
   :hook (typescript-mode . rainbow-delimiters-mode)
-  :config
-  (set-electric! 'typescript-mode
-    :chars '(?\} ?\)) :words '("||" "&&"))
-  (set-ligatures! 'typescript-mode
-    ;; Functional
-    :def "function"
-    :lambda "() =>"
-    :composition "compose"
-    ;; Types
-    :null "null"
-    :true "true" :false "false"
-    :int "number"
-    :str "string"
-    :bool "boolean"
-    ;; Flow
-    :not "!"
-    :and "&&" :or "||"
-    :for "for"
-    :return "return" :yield "import")
+  :hook (typescript-tsx-mode . rainbow-delimiters-mode)
+  :commands typescript-tsx-mode
+  :init
+  ;; REVIEW We associate TSX files with `typescript-tsx-mode' derived from
+  ;;        `web-mode' because `typescript-mode' does not officially support
+  ;;        JSX/TSX. See emacs-typescript/typescript.el#4
+  (add-to-list 'auto-mode-alist
+               (cons "\\.tsx\\'"
+                     (if (featurep! :lang web)
+                         #'typescript-tsx-mode
+                       #'typescript-mode)))
+
+  (when (featurep! :checkers syntax)
+    (after! flycheck
+      (flycheck-add-mode 'javascript-eslint 'web-mode)
+      (flycheck-add-mode 'javascript-eslint 'typescript-mode)
+      (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode)
+      (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)
+      (unless (featurep! +lsp)
+        (flycheck-add-next-checker 'typescript-tide '(warning . javascript-eslint) 'append)
+        (flycheck-add-mode 'typescript-tide 'typescript-tsx-mode))
+      (add-hook! 'typescript-tsx-mode-hook
+        (defun +javascript-disable-tide-checkers-h ()
+          (pushnew! flycheck-disabled-checkers
+                    'javascript-jshint
+                    'tsx-tide
+                    'jsx-tide)))))
+  :config
+  (when (fboundp 'web-mode)
+    (define-derived-mode typescript-tsx-mode web-mode "TypeScript-TSX"))
+
+  (set-docsets! '(typescript-mode typescript-tsx-mode)
+    :add "TypeScript" "AngularTS")
+  (set-electric! '(typescript-mode typescript-tsx-mode)
+    :chars '(?\} ?\))
+    :words '("||" "&&"))
   ;; HACK Fixes comment continuation on newline
+  (autoload 'js2-line-break "js2-mode" nil t)
   (setq-hook! 'typescript-mode-hook
-    comment-line-break-function #'js2-line-break))
-
-;; REVIEW We associate TSX files with `typescript-tsx-mode' derived from
-;;        `web-mode' because `typescript-mode' does not officially support
-;;        JSX/TSX. See
-;;        https://github.com/emacs-typescript/typescript.el/issues/4
-(if (featurep! :lang web)
-    (progn
-      (define-derived-mode typescript-tsx-mode web-mode "TypeScript-tsx")
-      (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-tsx-mode))
-
-      (add-hook 'typescript-tsx-mode-hook #'emmet-mode)
-
-      (after! flycheck
-        (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)
-        (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode)))
-  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode)))
-
-(after! (:any typescript-mode web-mode)
-  (set-docsets! '(typescript-mode typescript-tsx-mode) "TypeScript" "AngularTS"))
-
-
-;;;###package coffee-mode
-(setq coffee-indent-like-python-mode t)
-(after! coffee-mode
-  (set-docsets! 'coffee-mode "CoffeeScript"))
+    comment-line-break-function #'js2-line-break
+
+    ;; Most projects use either eslint, prettier, .editorconfig, or tsf in order
+    ;; to specify indent level and formatting. In the event that no
+    ;; project-level config is specified (very rarely these days), the community
+    ;; default is 2, not 4. However, respect what is in tsfmt.json if it is
+    ;; present in the project
+    typescript-indent-level
+    (or (and (bound-and-true-p tide-mode)
+             (plist-get (tide-tsfmt-options) :indentSize))
+        typescript-indent-level)))
 
 
 ;;
 ;;; Tools
 
-(add-hook! '(js2-mode-local-vars-hook
-             typescript-mode-local-vars-hook
+(add-hook! '(typescript-mode-local-vars-hook
              typescript-tsx-mode-local-vars-hook
              web-mode-local-vars-hook
              rjsx-mode-local-vars-hook)



;;
;; Major modes

(use-package! js2-mode
  :mode "\\.[mc]?js\\'"
  :mode "\\.es6\\'"
  :interpreter "node"
  :commands js2-line-break
  :config
  (setq js-chain-indent t
        ;; Don't mishighlight shebang lines
        js2-skip-preprocessor-directives t
        ;; let flycheck handle this

to tide."
    (let ((buffer-file-name (buffer-file-name (buffer-base-buffer))))
      (when (derived-mode-p 'js-mode 'typescript-mode 'typescript-tsx-mode)
        (if (null buffer-file-name)
            ;; necessary because `tide-setup' and `lsp' will error if not a
            ;; file-visiting buffer
            (add-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h
                      nil 'local)
          (or (if (featurep! +lsp) (lsp!))
              ;; fall back to tide
              (if (executable-find "node")
                  (and (require 'tide nil t)
                       (progn (tide-setup) tide-mode))
                (ignore
                 (doom-log "Couldn't start tide because 'node' is missing"))))
          (remove-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h
                       'local))))))


(use-package! tide
  :hook (tide-mode . tide-hl-identifier-mode)
  :config
  (set-company-backend! 'tide-mode 'company-tide)
  ;; navigation
  (set-lookup-handlers! 'tide-mode :async t
    :xref-backend #'xref-tide-xref-backend
    :documentation #'tide-documentation-at-point)
  (set-popup-rule! "^\\*tide-documentation" :quit t)

  (setq tide-completion-detailed t
        tide-always-show-documentation t
        ;; Fix #1792: by default, tide ignores payloads larger than 100kb. This
        ;; is too small for larger projects that produce long completion lists,
        ;; so we up it to 512kb.
        tide-server-max-response-length 524288
        ;; We'll handle it
        tide-completion-setup-company-backend nil)

  ;; Resolve to `doom-project-root' if `tide-project-root' fails
  (advice-add #'tide-project-root :override #'+javascript-tide-project-root-a)

  ;; Cleanup tsserver when no tide buffers are left
  (add-hook! 'tide-mode-hook
    (add-hook 'kill-buffer-hook #'+javascript-cleanup-tide-processes-h
              nil 'local))

  ;; Eldoc is activated too soon and disables itself, thinking there is no eldoc
  ;; support in the current buffer, so we must re-enable it later once eldoc
