diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Changelog for purescript-tsd-gen
 
+## 0.2.0.0
+
+* Support for PureScript v0.12.0.
+* Support `Data.Variant.Variant` from [purescript-variant](https://github.com/natefaubion/purescript-variant).
+* Support `Data.Nullable.Nullable` from [purescript-nullable](https://github.com/purescript-contrib/purescript-nullable).
+
 ## 0.1.0.0
 
 Initial release.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -80,10 +80,16 @@
   - `Fn3 a0 a1 a2 r` --> `(_0: a0, _1: a1, _2: a2) => r`
   - ...
   - `Fn10 a0 a1 .. a9 r` --> `(_0: a0, ..., _9: a9) => r`
+- `Effect`
+  - `Effect a` -> `() => a`
 - `Control.Monad.Eff`
   - `Eff e r` -> `() => r`
 - `Data.StrMap.StrMap`
   - `StrMap t` --> `{[_: string]: t}`
+- `Data.Variant` (from [purescript-variant](https://github.com/natefaubion/purescript-variant))
+  - `Variant (tag1 :: Type1, tag2 :: Type2)` --> `{type: "tag1", value: Type1} | {type: "tag2", value: Type2}`
+- `Data.Nullable` (from [purescript-nullable](https://github.com/purescript-contrib/purescript-nullable))
+  - `Nullable a` --> `a | null`
 
 ## User-defined Data Types
 
diff --git a/purescript-tsd-gen.cabal b/purescript-tsd-gen.cabal
--- a/purescript-tsd-gen.cabal
+++ b/purescript-tsd-gen.cabal
@@ -1,11 +1,11 @@
--- This file has been generated from package.yaml by hpack version 0.20.0.
+-- This file has been generated from package.yaml by hpack version 0.28.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 4c7dc0f1a89f41905e8219c5421e4ecc369cef143207028e98886b4720c92c02
+-- hash: 1aedd6caf4264346ee5c05b61e9cafec76a70631574a1ea5be5042588780f16f
 
 name:           purescript-tsd-gen
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       TypeScript Declaration File (.d.ts) generator for PureScript
 description:    Please see the README on Github at <https://github.com/minoki/purescript-tsd-gen#readme>
 category:       Language
@@ -18,7 +18,6 @@
 license-file:   LICENSE
 build-type:     Simple
 cabal-version:  >= 1.10
-
 extra-source-files:
     ChangeLog.md
     README.md
@@ -38,7 +37,7 @@
     , directory
     , filepath
     , mtl
-    , purescript
+    , purescript >=0.12.0
     , text
   exposed-modules:
       Language.PureScript.TsdGen.Module
@@ -61,7 +60,7 @@
     , filepath
     , mtl
     , optparse-applicative
-    , purescript
+    , purescript >=0.12.0
     , purescript-tsd-gen
     , text
   other-modules:
diff --git a/src/Language/PureScript/TsdGen/Module.hs b/src/Language/PureScript/TsdGen/Module.hs
--- a/src/Language/PureScript/TsdGen/Module.hs
+++ b/src/Language/PureScript/TsdGen/Module.hs
@@ -55,7 +55,8 @@
 
 recursivelyLoadExterns :: FilePath -> ModuleName -> StateT (Environment, Map.Map ModuleName (Maybe ExternsFile)) (ExceptT ModuleProcessingError IO) ()
 recursivelyLoadExterns dir moduleName
-  | moduleName == ModuleName [ProperName C.prim] = return ()
+  | moduleName == ModuleName [ProperName C.prim] = return () -- ~v0.11.7
+  | moduleName `List.elem` C.primModules = return () -- v0.12.0~
   | otherwise = do
   ef <- lift (readExternsForModule dir moduleName)
   modify (second (Map.insert moduleName (Just ef)))
@@ -225,7 +226,7 @@
                      -- Foreign type: just use 'any' type.
                      -- External '.d.ts' file needs to be supplied for better typing.
                      emitTypeDeclaration (Just "foreign") name typeParameters (TSUnknown "foreign")
-                 where builtins = [qnFn0,qnFn2,qnFn3,qnFn4,qnFn5,qnFn6,qnFn7,qnFn8,qnFn9,qnFn10,qnStrMap]
+                 where builtins = [qnFn0,qnFn2,qnFn3,qnFn4,qnFn5,qnFn6,qnFn7,qnFn8,qnFn9,qnFn10,qnStrMap,qnEffect,qnNullable]
                        n = numberOfTypeParams edTypeKind
                        typeParameters = map (\i -> "a" <> T.pack (show i)) [0..n-1]
 
diff --git a/src/Language/PureScript/TsdGen/Types.hs b/src/Language/PureScript/TsdGen/Types.hs
--- a/src/Language/PureScript/TsdGen/Types.hs
+++ b/src/Language/PureScript/TsdGen/Types.hs
@@ -40,13 +40,14 @@
 
 -- TypeScript types
 data TSType = TSAny
+            | TSUndefined
+            | TSNull
             | TSNever
             | TSNumber
             | TSBoolean
             | TSString
             | TSFunction {- type parameters -} [Text] {- parameter types -} [TSType] TSType
             | TSArray TSType
-            | TSUndefined
             | TSRecord [Field]
             | TSStrMap TSType -- Data.StrMap.StrMap <=> {[_: string]: T}
             | TSTyVar Text
@@ -85,7 +86,7 @@
 tyFn9 = TypeConstructor qnFn9
 tyFn10 = TypeConstructor qnFn10
 
--- Data.StrMap:
+-- Data.StrMap (from purescript-maps)
 -- foreign import data StrMap :: Type -> Type
 qnStrMap = Qualified (Just (moduleNameFromString "Data.StrMap")) (ProperName "StrMap")
 tyStrMap :: Type
@@ -95,6 +96,20 @@
 -- foreign import data Eff :: # Effect -> Type -> Type
 tyEff = TypeConstructor (Qualified (Just (moduleNameFromString "Control.Monad.Eff")) (ProperName "Eff"))
 
+-- Effect (from purescript-effect)
+-- foreign import data Effect :: Type -> Type
+qnEffect = Qualified (Just (moduleNameFromString "Effect")) (ProperName "Effect")
+tyEffect = TypeConstructor qnEffect
+
+-- Data.Variant (from purescript-variant)
+-- foreign import data Variant :: # Type -> Type
+tyVariant = TypeConstructor (Qualified (Just (moduleNameFromString "Data.Variant")) (ProperName "Variant"))
+
+-- Data.Nullable (from purescript-nullable)
+-- foreign import data Nullable :: Type -> Type
+qnNullable = Qualified (Just (moduleNameFromString "Data.Nullable")) (ProperName "Nullable")
+tyNullable = TypeConstructor qnNullable
+
 constraintToType :: Constraint -> Type
 constraintToType ct = foldl TypeApp (TypeConstructor qDictTypeName) (constraintArgs ct)
   where qDictTypeName = fmap coerceProperName (constraintClass ct)
@@ -146,6 +161,10 @@
       | tcon == tyRecord = case rowToList a0 of
                              (pairs, _) -> TSRecord <$> traverse (\(label,ty) -> mkField label <$> go ty) pairs
       | tcon == tyFn0 = tsFunction go [] a0
+      | tcon == tyEffect = tsFunction go [] a0
+      | tcon == tyVariant = case rowToList a0 of
+                              (pairs, _) -> TSUnion <$> traverse (\(label,ty) -> (\ty' -> TSRecord [mkField "type" (TSStringLit $ runLabel label), mkField "value" ty']) <$> go ty) pairs
+      | tcon == tyNullable = (\ty -> TSUnion [ty, TSNull]) <$> go a0
     go ty@(ForAll name inner _) = getKindsIn ty $ \kinds ->
       if List.lookup name kinds == Just kindType
       then withReaderT (\r -> r { ttcUnboundTyVars = name : ttcUnboundTyVars r }) (go inner)
@@ -234,6 +253,8 @@
 showTSTypePrec :: Int -> TSType -> Text
 showTSTypePrec prec ty = case ty of
   TSAny -> "any"
+  TSUndefined -> "undefined"
+  TSNull -> "null"
   TSNever -> "never"
   TSNumber -> "number"
   TSBoolean -> "boolean"
@@ -242,7 +263,6 @@
   TSFunction tp params ret -> showParenIf (prec > 0) $ "<" <> T.intercalate ", " (map properToJs tp) <> ">(" <> showFunctionParameters params <> ") => " <> showTSType ret
   TSArray elemTy -> "Array< " <> showTSType elemTy <> " >" -- TODO: Use ReadonlyArray?
   TSStrMap elemTy -> "{[_: string]: " <> showTSType elemTy <> "}"
-  TSUndefined -> "undefined"
   TSRecord [] -> "{}"
   TSRecord fields -> "{ " <> T.intercalate "; " (map showField fields) <> " }"
   TSUnknown desc -> "any /* " <>  desc <> " */"
